From 91ded4d678d564ae1c57623914e0df4e11d2f31b Mon Sep 17 00:00:00 2001 From: joocer Date: Tue, 28 Jan 2025 23:09:29 +0000 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Have=20a=20killer=20question=20on?= =?UTF-8?q?=20optimisation=20strategies=20#2297?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- opteryx/functions/string_functions.py | 5 +- .../simple_aggregate_and_group_node.py | 99 +- .../optimizer/strategies/constant_folding.py | 3 + .../strategies/optimization_strategy.py | 4 + .../strategies/projection_pushdown.py | 9 +- opteryx/planner/physical_planner.py | 2 +- opteryx/planner/sql_rewriter.py | 11 +- .../third_party/mrabarnett/regex/__init__.py | 3 + .../mrabarnett/regex/_regex_core.py | 4495 +++ opteryx/third_party/mrabarnett/regex/regex.py | 746 + opteryx/third_party/mrabarnett/test_regex.py | 4494 +++ setup.py | 7 + tests/query_planner/test_r_strings.py | 55 + tests/sql_battery/tests/clickbench.run_tests | 2 +- third_party/mrabarnett/LICENSE.txt | 208 + third_party/mrabarnett/_regex.c | 26328 +++++++++++++ third_party/mrabarnett/_regex.h | 237 + third_party/mrabarnett/_regex_unicode.c | 31399 ++++++++++++++++ third_party/mrabarnett/_regex_unicode.h | 315 + third_party/mrabarnett/readme.rst | 1034 + 20 files changed, 69397 insertions(+), 59 deletions(-) create mode 100644 opteryx/third_party/mrabarnett/regex/__init__.py create mode 100644 opteryx/third_party/mrabarnett/regex/_regex_core.py create mode 100644 opteryx/third_party/mrabarnett/regex/regex.py create mode 100644 opteryx/third_party/mrabarnett/test_regex.py create mode 100644 tests/query_planner/test_r_strings.py create mode 100644 third_party/mrabarnett/LICENSE.txt create mode 100644 third_party/mrabarnett/_regex.c create mode 100644 third_party/mrabarnett/_regex.h create mode 100644 third_party/mrabarnett/_regex_unicode.c create mode 100644 third_party/mrabarnett/_regex_unicode.h create mode 100644 third_party/mrabarnett/readme.rst diff --git a/opteryx/functions/string_functions.py b/opteryx/functions/string_functions.py index 856961a36..41a0bd414 100644 --- a/opteryx/functions/string_functions.py +++ b/opteryx/functions/string_functions.py @@ -357,16 +357,13 @@ def match_against(arr, val): def regex_replace(array, _pattern, _replacement): - import re - + from opteryx.third_party.mrabarnett import regex as re import pyarrow pattern = _pattern[0] replacement = _replacement[0] compiled_pattern = re.compile(pattern) - return compute.replace_substring_regex(array, pattern, replacement) - # Apply the regex replacement to each element in the array vectorized_replace = numpy.vectorize(lambda x: compiled_pattern.sub(replacement, x)) return pyarrow.array(vectorized_replace(array), type=pyarrow.string()) diff --git a/opteryx/operators/simple_aggregate_and_group_node.py b/opteryx/operators/simple_aggregate_and_group_node.py index f8e33597b..35c682d2d 100644 --- a/opteryx/operators/simple_aggregate_and_group_node.py +++ b/opteryx/operators/simple_aggregate_and_group_node.py @@ -12,6 +12,8 @@ and are collected as, a single value. """ +import time + import numpy import pyarrow from orso.types import OrsoTypes @@ -21,6 +23,7 @@ from opteryx.managers.expression import evaluate_and_append from opteryx.managers.expression import get_all_nodes_of_type from opteryx.models import QueryProperties +from opteryx.operators.aggregate_node import AGGREGATORS from opteryx.operators.aggregate_node import build_aggregations from opteryx.operators.aggregate_node import extract_evaluations from opteryx.operators.aggregate_node import project @@ -28,6 +31,31 @@ from . import BasePlanNode +def build_finalizer_aggregations(aggregators): + column_map = {} + aggs = [] + + if not isinstance(aggregators, list): + aggregators = [aggregators] + + for root in aggregators: + for aggregator in get_all_nodes_of_type(root, select_nodes=(NodeType.AGGREGATOR,)): + count_options = None + + field_name = aggregator.schema_column.identity + if aggregator.value == "COUNT": + function = AGGREGATORS["SUM"] + else: + function = AGGREGATORS[aggregator.value] + # if the array agg is distinct, base off that function instead + aggs.append((field_name, function, count_options)) + column_map[aggregator.schema_column.identity] = f"{field_name}_{function}".replace( + "_hash_", "_" + ) + + return column_map, aggs + + class SimpleAggregateAndGroupNode(BasePlanNode): SIMPLE_AGGREGATES = {"SUM", "MIN", "MAX", "COUNT"} @@ -63,7 +91,11 @@ def __init__(self, properties: QueryProperties, **parameters): self.group_by_columns = list({node.schema_column.identity for node in self.groups}) self.column_map, self.aggregate_functions = build_aggregations(self.aggregates) - self.accumulator = {} + self.finalizer_map, self.finalizer_aggregations = build_finalizer_aggregations( + self.aggregates + ) + + self.buffer = [] @property def config(self): # pragma: no cover @@ -76,20 +108,23 @@ def name(self): # pragma: no cover return "Group By Simple" def execute(self, morsel: pyarrow.Table, **kwargs): + internal_names = list(self.column_map.values()) + self.group_by_columns + column_names = list(self.column_map.keys()) + self.group_by_columns + if morsel == EOS: - py_dict = {} - for k, v in self.accumulator.items(): - for i, group in enumerate(self.group_by_columns): - if group not in py_dict: - py_dict[group] = [k[i]] - else: - py_dict[group].append(k[i]) - for column_id, value in v.items(): - if column_id not in py_dict: - py_dict[column_id] = [value] - else: - py_dict[column_id].append(value) - yield pyarrow.Table.from_pydict(py_dict) + start = time.monotonic_ns() + + internal_names = list(self.finalizer_map.values()) + self.group_by_columns + column_names = list(self.finalizer_map.keys()) + self.group_by_columns + + groups = pyarrow.concat_tables(self.buffer, promote_options="permissive") + groups = groups.group_by(self.group_by_columns) + groups = groups.aggregate(self.finalizer_aggregations) + groups = groups.select(internal_names) + groups = groups.rename_columns(column_names) + + self.statistics.time_groupby_finalize += time.monotonic_ns() - start + yield groups yield EOS return @@ -108,37 +143,13 @@ def execute(self, morsel: pyarrow.Table, **kwargs): ) # use pyarrow to do phase 1 of the group by + st = time.monotonic_ns() groups = morsel.group_by(self.group_by_columns) groups = groups.aggregate(self.aggregate_functions) - # project to the desired column names from the pyarrow names - groups = groups.select(list(self.column_map.values()) + self.group_by_columns) - groups = groups.rename_columns(list(self.column_map.keys()) + self.group_by_columns) - - # we now merge the results into the accumulator - for row in groups.to_pylist(): - for aggregate in self.aggregates: - column_id = aggregate.schema_column.identity - value = row[column_id] - groups = tuple(row[group] for group in self.group_by_columns) - - if groups not in self.accumulator: - self.accumulator[groups] = {} - - if self.accumulator[groups].get(column_id) is None: - self.accumulator[groups][column_id] = value - elif aggregate.value == "COUNT" or aggregate.value == "SUM": - self.accumulator[groups][column_id] += value - elif aggregate.value == "MIN": - self.accumulator[groups][column_id] = min( - self.accumulator[groups][column_id], value - ) - elif aggregate.value == "MAX": - self.accumulator[groups][column_id] = max( - self.accumulator[groups][column_id], value - ) - else: - raise NotImplementedError( - f"SimpleAggregateAndGroupNode does not support {aggregate.value}" - ) + groups = groups.select(internal_names) + groups = groups.rename_columns(column_names) + self.statistics.time_pregrouping += time.monotonic_ns() - st + + self.buffer.append(groups) yield None diff --git a/opteryx/planner/optimizer/strategies/constant_folding.py b/opteryx/planner/optimizer/strategies/constant_folding.py index 81ae02970..aa2d7ca81 100644 --- a/opteryx/planner/optimizer/strategies/constant_folding.py +++ b/opteryx/planner/optimizer/strategies/constant_folding.py @@ -259,6 +259,8 @@ def fold_constants(root: Node, statistics: QueryStatistics) -> Node: # fold costants in function parameters - this is generally aggregations we're affecting here if root.parameters: + if isinstance(root.parameters, tuple): + root.parameters = list(root.parameters) for i, param in enumerate(root.parameters): root.parameters[i] = fold_constants(param, statistics) @@ -322,6 +324,7 @@ def visit(self, node: LogicalPlanNode, context: OptimizerContext) -> OptimizerCo if node.node_type == LogicalPlanStepType.AggregateAndGroup: node.groups = [g.centre if g.node_type == NodeType.NESTED else g for g in node.groups] + node.groups = [fold_constants(g, self.statistics) for g in node.groups] context.optimized_plan[context.node_id] = node return context diff --git a/opteryx/planner/optimizer/strategies/optimization_strategy.py b/opteryx/planner/optimizer/strategies/optimization_strategy.py index 02223231f..2899bb9b8 100644 --- a/opteryx/planner/optimizer/strategies/optimization_strategy.py +++ b/opteryx/planner/optimizer/strategies/optimization_strategy.py @@ -31,6 +31,7 @@ def __init__(self, tree: LogicalPlan): self.seen_projections: int = 0 self.seen_unions: int = 0 self.seen_distincts: int = 0 + self.seen_projects_since_distinct: int = 0 self.collected_predicates: list = [] """We collect predicates we should be able to push to reads and joins""" @@ -44,6 +45,9 @@ def __init__(self, tree: LogicalPlan): self.collected_limits: list = [] """We collect limits to to to eliminate rows earlier""" + self.distincted_indentities: set = set() + """The columns that implicitly exist in the plan because of a distinct""" + class OptimizationStrategy: def __init__(self, statistics): diff --git a/opteryx/planner/optimizer/strategies/projection_pushdown.py b/opteryx/planner/optimizer/strategies/projection_pushdown.py index 6b1085fe7..24cb5a949 100644 --- a/opteryx/planner/optimizer/strategies/projection_pushdown.py +++ b/opteryx/planner/optimizer/strategies/projection_pushdown.py @@ -48,20 +48,13 @@ def visit(self, node: LogicalPlanNode, context: OptimizerContext) -> OptimizerCo # If we're at the something other than the top project (e.g. in a subquery) in a plan we # may be able to remove some columns (and potentially some evaluations) if the columns # aren't referenced in the outer query. - if node.node_type == LogicalPlanStepType.Distinct: - context.seen_distincts += 1 if node.node_type == LogicalPlanStepType.Union: context.seen_unions += 1 if node.node_type == LogicalPlanStepType.Project: - if ( - context.seen_distincts == 0 - and context.seen_unions == 0 - and context.seen_projections > 0 - ): + if context.seen_unions == 0 and context.seen_projections > 0: node.columns = [ n for n in node.columns if n.schema_column.identity in node.pre_update_columns ] - self.seen_distincts = 0 if context.seen_unions == 0: context.seen_projections += 1 diff --git a/opteryx/planner/physical_planner.py b/opteryx/planner/physical_planner.py index b57a74b59..3ea69fdd7 100644 --- a/opteryx/planner/physical_planner.py +++ b/opteryx/planner/physical_planner.py @@ -26,7 +26,7 @@ def create_physical_plan(logical_plan, query_properties) -> PhysicalPlan: else: node = operators.AggregateNode(query_properties, **{k:v for k,v in node_config.items() if k in ("aggregates", "all_relations")}) elif node_type == LogicalPlanStepType.AggregateAndGroup: - if False and all(agg.value in operators.SimpleAggregateAndGroupNode.SIMPLE_AGGREGATES for agg in node_config["aggregates"]): + if all(agg.value in operators.SimpleAggregateAndGroupNode.SIMPLE_AGGREGATES and agg.duplicate_treatment != "Distinct" for agg in node_config["aggregates"]): node = operators.SimpleAggregateAndGroupNode(query_properties, **{k:v for k,v in node_config.items() if k in ("aggregates", "groups", "projection", "all_relations")}) else: node = operators.AggregateAndGroupNode(query_properties, **{k:v for k,v in node_config.items() if k in ("aggregates", "groups", "projection", "all_relations")}) diff --git a/opteryx/planner/sql_rewriter.py b/opteryx/planner/sql_rewriter.py index 2899d7528..69eb5c6ac 100644 --- a/opteryx/planner/sql_rewriter.py +++ b/opteryx/planner/sql_rewriter.py @@ -143,13 +143,22 @@ def sql_parts(string): ) # Match ", ', b", b', ` # We match b prefixes separately after the non-prefix versions - quoted_strings = re.compile(r'("[^"]*"|\'[^\']*\'|\b[bB]"[^"]*"|\b[bB]\'[^\']*\'|`[^`]*`)') + quoted_strings = re.compile( + r'("[^"]*"|\'[^\']*\'|\b[bB]"[^"]*"|\b[bB]\'[^\']*\'|\b[rR]"[^"]*"|\b[rR]\'[^\']*\'|`[^`]*`)' + ) parts = [] for part in quoted_strings.split(string): if part and part[-1] in ("'", '"', "`"): if part[0] in ("b", "B"): parts.append(f"blob({part[1:]})") + elif part[0] in ("r", "R"): + # We take the raw string and encode it, pass it into the + # plan as the encoded string and let the engine decode it + from base64 import b85encode + + encoded_part = b85encode(part[2:-1].encode()).decode() + parts.append(f"BASE85_DECODE('{encoded_part}')") else: parts.append(part) else: diff --git a/opteryx/third_party/mrabarnett/regex/__init__.py b/opteryx/third_party/mrabarnett/regex/__init__.py new file mode 100644 index 000000000..eb06564ab --- /dev/null +++ b/opteryx/third_party/mrabarnett/regex/__init__.py @@ -0,0 +1,3 @@ +from .regex import * +from . import regex +__all__ = regex.__all__ diff --git a/opteryx/third_party/mrabarnett/regex/_regex_core.py b/opteryx/third_party/mrabarnett/regex/_regex_core.py new file mode 100644 index 000000000..af4de4037 --- /dev/null +++ b/opteryx/third_party/mrabarnett/regex/_regex_core.py @@ -0,0 +1,4495 @@ +# +# Secret Labs' Regular Expression Engine core module +# +# Copyright (c) 1998-2001 by Secret Labs AB. All rights reserved. +# +# This version of the SRE library can be redistributed under CNRI's +# Python 1.6 license. For any other use, please contact Secret Labs +# AB (info@pythonware.com). +# +# Portions of this engine have been developed in cooperation with +# CNRI. Hewlett-Packard provided funding for 1.6 integration and +# other compatibility work. +# +# 2010-01-16 mrab Python front-end re-written and extended + +import enum +import string +import unicodedata +from collections import defaultdict + +import regex._regex as _regex + +__all__ = ["A", "ASCII", "B", "BESTMATCH", "D", "DEBUG", "E", "ENHANCEMATCH", + "F", "FULLCASE", "I", "IGNORECASE", "L", "LOCALE", "M", "MULTILINE", "P", + "POSIX", "R", "REVERSE", "S", "DOTALL", "T", "TEMPLATE", "U", "UNICODE", + "V0", "VERSION0", "V1", "VERSION1", "W", "WORD", "X", "VERBOSE", "error", + "Scanner", "RegexFlag"] + +# The regex exception. +class error(Exception): + """Exception raised for invalid regular expressions. + + Attributes: + + msg: The unformatted error message + pattern: The regular expression pattern + pos: The position in the pattern where compilation failed, or None + lineno: The line number where compilation failed, unless pos is None + colno: The column number where compilation failed, unless pos is None + """ + + def __init__(self, message, pattern=None, pos=None): + newline = '\n' if isinstance(pattern, str) else b'\n' + self.msg = message + self.pattern = pattern + self.pos = pos + if pattern is not None and pos is not None: + self.lineno = pattern.count(newline, 0, pos) + 1 + self.colno = pos - pattern.rfind(newline, 0, pos) + + message = "{} at position {}".format(message, pos) + + if newline in pattern: + message += " (line {}, column {})".format(self.lineno, + self.colno) + + Exception.__init__(self, message) + +# The exception for when a positional flag has been turned on in the old +# behaviour. +class _UnscopedFlagSet(Exception): + pass + +# The exception for when parsing fails and we want to try something else. +class ParseError(Exception): + pass + +# The exception for when there isn't a valid first set. +class _FirstSetError(Exception): + pass + +# Flags. +class RegexFlag(enum.IntFlag): + A = ASCII = 0x80 # Assume ASCII locale. + B = BESTMATCH = 0x1000 # Best fuzzy match. + D = DEBUG = 0x200 # Print parsed pattern. + E = ENHANCEMATCH = 0x8000 # Attempt to improve the fit after finding the first + # fuzzy match. + F = FULLCASE = 0x4000 # Unicode full case-folding. + I = IGNORECASE = 0x2 # Ignore case. + L = LOCALE = 0x4 # Assume current 8-bit locale. + M = MULTILINE = 0x8 # Make anchors look for newline. + P = POSIX = 0x10000 # POSIX-style matching (leftmost longest). + R = REVERSE = 0x400 # Search backwards. + S = DOTALL = 0x10 # Make dot match newline. + U = UNICODE = 0x20 # Assume Unicode locale. + V0 = VERSION0 = 0x2000 # Old legacy behaviour. + V1 = VERSION1 = 0x100 # New enhanced behaviour. + W = WORD = 0x800 # Default Unicode word breaks. + X = VERBOSE = 0x40 # Ignore whitespace and comments. + T = TEMPLATE = 0x1 # Template (present because re module has it). + + def __repr__(self): + if self._name_ is not None: + return 'regex.%s' % self._name_ + + value = self._value_ + members = [] + negative = value < 0 + + if negative: + value = ~value + + for m in self.__class__: + if value & m._value_: + value &= ~m._value_ + members.append('regex.%s' % m._name_) + + if value: + members.append(hex(value)) + + res = '|'.join(members) + + if negative: + if len(members) > 1: + res = '~(%s)' % res + else: + res = '~%s' % res + + return res + + __str__ = object.__str__ + +globals().update(RegexFlag.__members__) + +DEFAULT_VERSION = VERSION1 + +_ALL_VERSIONS = VERSION0 | VERSION1 +_ALL_ENCODINGS = ASCII | LOCALE | UNICODE + +# The default flags for the various versions. +DEFAULT_FLAGS = {VERSION0: 0, VERSION1: FULLCASE} + +# The mask for the flags. +GLOBAL_FLAGS = (_ALL_VERSIONS | BESTMATCH | DEBUG | ENHANCEMATCH | POSIX | + REVERSE) +SCOPED_FLAGS = (FULLCASE | IGNORECASE | MULTILINE | DOTALL | WORD | VERBOSE | + _ALL_ENCODINGS) + +ALPHA = frozenset(string.ascii_letters) +DIGITS = frozenset(string.digits) +ALNUM = ALPHA | DIGITS +OCT_DIGITS = frozenset(string.octdigits) +HEX_DIGITS = frozenset(string.hexdigits) +SPECIAL_CHARS = frozenset("()|?*+{^$.[\\#") | frozenset([""]) +NAMED_CHAR_PART = ALNUM | frozenset(" -") +PROPERTY_NAME_PART = ALNUM | frozenset(" &_-.") +SET_OPS = ("||", "~~", "&&", "--") + +# The width of the code words inside the regex engine. +BYTES_PER_CODE = _regex.get_code_size() +BITS_PER_CODE = BYTES_PER_CODE * 8 + +# The repeat count which represents infinity. +UNLIMITED = (1 << BITS_PER_CODE) - 1 + +# The regular expression flags. +REGEX_FLAGS = {"a": ASCII, "b": BESTMATCH, "e": ENHANCEMATCH, "f": FULLCASE, + "i": IGNORECASE, "L": LOCALE, "m": MULTILINE, "p": POSIX, "r": REVERSE, + "s": DOTALL, "u": UNICODE, "V0": VERSION0, "V1": VERSION1, "w": WORD, "x": + VERBOSE} + +# The case flags. +CASE_FLAGS = FULLCASE | IGNORECASE +NOCASE = 0 +FULLIGNORECASE = FULLCASE | IGNORECASE + +FULL_CASE_FOLDING = UNICODE | FULLIGNORECASE + +CASE_FLAGS_COMBINATIONS = {0: 0, FULLCASE: 0, IGNORECASE: IGNORECASE, + FULLIGNORECASE: FULLIGNORECASE} + +# The number of digits in hexadecimal escapes. +HEX_ESCAPES = {"x": 2, "u": 4, "U": 8} + +# The names of the opcodes. +OPCODES = """ +FAILURE +SUCCESS +ANY +ANY_ALL +ANY_ALL_REV +ANY_REV +ANY_U +ANY_U_REV +ATOMIC +BOUNDARY +BRANCH +CALL_REF +CHARACTER +CHARACTER_IGN +CHARACTER_IGN_REV +CHARACTER_REV +CONDITIONAL +DEFAULT_BOUNDARY +DEFAULT_END_OF_WORD +DEFAULT_START_OF_WORD +END +END_OF_LINE +END_OF_LINE_U +END_OF_STRING +END_OF_STRING_LINE +END_OF_STRING_LINE_U +END_OF_WORD +FUZZY +GRAPHEME_BOUNDARY +GREEDY_REPEAT +GROUP +GROUP_CALL +GROUP_EXISTS +KEEP +LAZY_REPEAT +LOOKAROUND +NEXT +PROPERTY +PROPERTY_IGN +PROPERTY_IGN_REV +PROPERTY_REV +PRUNE +RANGE +RANGE_IGN +RANGE_IGN_REV +RANGE_REV +REF_GROUP +REF_GROUP_FLD +REF_GROUP_FLD_REV +REF_GROUP_IGN +REF_GROUP_IGN_REV +REF_GROUP_REV +SEARCH_ANCHOR +SET_DIFF +SET_DIFF_IGN +SET_DIFF_IGN_REV +SET_DIFF_REV +SET_INTER +SET_INTER_IGN +SET_INTER_IGN_REV +SET_INTER_REV +SET_SYM_DIFF +SET_SYM_DIFF_IGN +SET_SYM_DIFF_IGN_REV +SET_SYM_DIFF_REV +SET_UNION +SET_UNION_IGN +SET_UNION_IGN_REV +SET_UNION_REV +SKIP +START_OF_LINE +START_OF_LINE_U +START_OF_STRING +START_OF_WORD +STRING +STRING_FLD +STRING_FLD_REV +STRING_IGN +STRING_IGN_REV +STRING_REV +FUZZY_EXT +""" + +# Define the opcodes in a namespace. +class Namespace: + pass + +OP = Namespace() +for i, op in enumerate(OPCODES.split()): + setattr(OP, op, i) + +def _shrink_cache(cache_dict, args_dict, locale_sensitive, max_length, divisor=5): + """Make room in the given cache. + + Args: + cache_dict: The cache dictionary to modify. + args_dict: The dictionary of named list args used by patterns. + max_length: Maximum # of entries in cache_dict before it is shrunk. + divisor: Cache will shrink to max_length - 1/divisor*max_length items. + """ + # Toss out a fraction of the entries at random to make room for new ones. + # A random algorithm was chosen as opposed to simply cache_dict.popitem() + # as popitem could penalize the same regular expression repeatedly based + # on its internal hash value. Being random should spread the cache miss + # love around. + cache_keys = tuple(cache_dict.keys()) + overage = len(cache_keys) - max_length + if overage < 0: + # Cache is already within limits. Normally this should not happen + # but it could due to multithreading. + return + + number_to_toss = max_length // divisor + overage + + # The import is done here to avoid a circular dependency. + import random + if not hasattr(random, 'sample'): + # Do nothing while resolving the circular dependency: + # re->random->warnings->tokenize->string->re + return + + for doomed_key in random.sample(cache_keys, number_to_toss): + try: + del cache_dict[doomed_key] + except KeyError: + # Ignore problems if the cache changed from another thread. + pass + + # Rebuild the arguments and locale-sensitivity dictionaries. + args_dict.clear() + sensitivity_dict = {} + for pattern, pattern_type, flags, args, default_version, locale in tuple(cache_dict): + args_dict[pattern, pattern_type, flags, default_version, locale] = args + try: + sensitivity_dict[pattern_type, pattern] = locale_sensitive[pattern_type, pattern] + except KeyError: + pass + + locale_sensitive.clear() + locale_sensitive.update(sensitivity_dict) + +def _fold_case(info, string): + "Folds the case of a string." + flags = info.flags + if (flags & _ALL_ENCODINGS) == 0: + flags |= info.guess_encoding + + return _regex.fold_case(flags, string) + +def is_cased_i(info, char): + "Checks whether a character is cased." + return len(_regex.get_all_cases(info.flags, char)) > 1 + +def is_cased_f(flags, char): + "Checks whether a character is cased." + return len(_regex.get_all_cases(flags, char)) > 1 + +def _compile_firstset(info, fs): + "Compiles the firstset for the pattern." + reverse = bool(info.flags & REVERSE) + fs = _check_firstset(info, reverse, fs) + if not fs: + return [] + + # Compile the firstset. + return fs.compile(reverse) + +def _check_firstset(info, reverse, fs): + "Checks the firstset for the pattern." + if not fs or None in fs: + return None + + # If we ignore the case, for simplicity we won't build a firstset. + members = set() + case_flags = NOCASE + for i in fs: + if isinstance(i, Character) and not i.positive: + return None + +# if i.case_flags: +# if isinstance(i, Character): +# if is_cased_i(info, i.value): +# return [] +# elif isinstance(i, SetBase): +# return [] + case_flags |= i.case_flags + members.add(i.with_flags(case_flags=NOCASE)) + + if case_flags == (FULLCASE | IGNORECASE): + return None + + # Build the firstset. + fs = SetUnion(info, list(members), case_flags=case_flags & ~FULLCASE, + zerowidth=True) + fs = fs.optimise(info, reverse, in_set=True) + + return fs + +def _flatten_code(code): + "Flattens the code from a list of tuples." + flat_code = [] + for c in code: + flat_code.extend(c) + + return flat_code + +def make_case_flags(info): + "Makes the case flags." + flags = info.flags & CASE_FLAGS + + # Turn off FULLCASE if ASCII is turned on. + if info.flags & ASCII: + flags &= ~FULLCASE + + return flags + +def make_character(info, value, in_set=False): + "Makes a character literal." + if in_set: + # A character set is built case-sensitively. + return Character(value) + + return Character(value, case_flags=make_case_flags(info)) + +def make_ref_group(info, name, position): + "Makes a group reference." + return RefGroup(info, name, position, case_flags=make_case_flags(info)) + +def make_string_set(info, name): + "Makes a string set." + return StringSet(info, name, case_flags=make_case_flags(info)) + +def make_property(info, prop, in_set): + "Makes a property." + if in_set: + return prop + + return prop.with_flags(case_flags=make_case_flags(info)) + +def _parse_pattern(source, info): + "Parses a pattern, eg. 'a|b|c'." + branches = [parse_sequence(source, info)] + while source.match("|"): + branches.append(parse_sequence(source, info)) + + if len(branches) == 1: + return branches[0] + return Branch(branches) + +def parse_sequence(source, info): + "Parses a sequence, eg. 'abc'." + sequence = [None] + case_flags = make_case_flags(info) + while True: + saved_pos = source.pos + ch = source.get() + if ch in SPECIAL_CHARS: + if ch in ")|": + # The end of a sequence. At the end of the pattern ch is "". + source.pos = saved_pos + break + elif ch == "\\": + # An escape sequence outside a set. + sequence.append(parse_escape(source, info, False)) + elif ch == "(": + # A parenthesised subpattern or a flag. + element = parse_paren(source, info) + if element is None: + case_flags = make_case_flags(info) + else: + sequence.append(element) + elif ch == ".": + # Any character. + if info.flags & DOTALL: + sequence.append(AnyAll()) + elif info.flags & WORD: + sequence.append(AnyU()) + else: + sequence.append(Any()) + elif ch == "[": + # A character set. + sequence.append(parse_set(source, info)) + elif ch == "^": + # The start of a line or the string. + if info.flags & MULTILINE: + if info.flags & WORD: + sequence.append(StartOfLineU()) + else: + sequence.append(StartOfLine()) + else: + sequence.append(StartOfString()) + elif ch == "$": + # The end of a line or the string. + if info.flags & MULTILINE: + if info.flags & WORD: + sequence.append(EndOfLineU()) + else: + sequence.append(EndOfLine()) + else: + if info.flags & WORD: + sequence.append(EndOfStringLineU()) + else: + sequence.append(EndOfStringLine()) + elif ch in "?*+{": + # Looks like a quantifier. + counts = parse_quantifier(source, info, ch) + if counts: + # It _is_ a quantifier. + apply_quantifier(source, info, counts, case_flags, ch, + saved_pos, sequence) + sequence.append(None) + else: + # It's not a quantifier. Maybe it's a fuzzy constraint. + constraints = parse_fuzzy(source, info, ch, case_flags) + if constraints: + # It _is_ a fuzzy constraint. + apply_constraint(source, info, constraints, case_flags, + saved_pos, sequence) + sequence.append(None) + else: + # The element was just a literal. + sequence.append(Character(ord(ch), + case_flags=case_flags)) + else: + # A literal. + sequence.append(Character(ord(ch), case_flags=case_flags)) + else: + # A literal. + sequence.append(Character(ord(ch), case_flags=case_flags)) + + sequence = [item for item in sequence if item is not None] + return Sequence(sequence) + +def apply_quantifier(source, info, counts, case_flags, ch, saved_pos, + sequence): + element = sequence.pop() + if element is None: + if sequence: + raise error("multiple repeat", source.string, saved_pos) + raise error("nothing to repeat", source.string, saved_pos) + + if isinstance(element, (GreedyRepeat, LazyRepeat, PossessiveRepeat)): + raise error("multiple repeat", source.string, saved_pos) + + min_count, max_count = counts + saved_pos = source.pos + ch = source.get() + if ch == "?": + # The "?" suffix that means it's a lazy repeat. + repeated = LazyRepeat + elif ch == "+": + # The "+" suffix that means it's a possessive repeat. + repeated = PossessiveRepeat + else: + # No suffix means that it's a greedy repeat. + source.pos = saved_pos + repeated = GreedyRepeat + + # Ignore the quantifier if it applies to a zero-width item or the number of + # repeats is fixed at 1. + if not element.is_empty() and (min_count != 1 or max_count != 1): + element = repeated(element, min_count, max_count) + + sequence.append(element) + +def apply_constraint(source, info, constraints, case_flags, saved_pos, + sequence): + element = sequence.pop() + if element is None: + raise error("nothing for fuzzy constraint", source.string, saved_pos) + + # If a group is marked as fuzzy then put all of the fuzzy part in the + # group. + if isinstance(element, Group): + element.subpattern = Fuzzy(element.subpattern, constraints) + sequence.append(element) + else: + sequence.append(Fuzzy(element, constraints)) + +_QUANTIFIERS = {"?": (0, 1), "*": (0, None), "+": (1, None)} + +def parse_quantifier(source, info, ch): + "Parses a quantifier." + q = _QUANTIFIERS.get(ch) + if q: + # It's a quantifier. + return q + + if ch == "{": + # Looks like a limited repeated element, eg. 'a{2,3}'. + counts = parse_limited_quantifier(source) + if counts: + return counts + + return None + +def is_above_limit(count): + "Checks whether a count is above the maximum." + return count is not None and count >= UNLIMITED + +def parse_limited_quantifier(source): + "Parses a limited quantifier." + saved_pos = source.pos + min_count = parse_count(source) + if source.match(","): + max_count = parse_count(source) + + # No minimum means 0 and no maximum means unlimited. + min_count = int(min_count or 0) + max_count = int(max_count) if max_count else None + else: + if not min_count: + source.pos = saved_pos + return None + + min_count = max_count = int(min_count) + + if not source.match ("}"): + source.pos = saved_pos + return None + + if is_above_limit(min_count) or is_above_limit(max_count): + raise error("repeat count too big", source.string, saved_pos) + + if max_count is not None and min_count > max_count: + raise error("min repeat greater than max repeat", source.string, + saved_pos) + + return min_count, max_count + +def parse_fuzzy(source, info, ch, case_flags): + "Parses a fuzzy setting, if present." + saved_pos = source.pos + + if ch != "{": + return None + + constraints = {} + try: + parse_fuzzy_item(source, constraints) + while source.match(","): + parse_fuzzy_item(source, constraints) + except ParseError: + source.pos = saved_pos + return None + + if source.match(":"): + constraints["test"] = parse_fuzzy_test(source, info, case_flags) + + if not source.match("}"): + raise error("expected }", source.string, source.pos) + + return constraints + +def parse_fuzzy_item(source, constraints): + "Parses a fuzzy setting item." + saved_pos = source.pos + try: + parse_cost_constraint(source, constraints) + except ParseError: + source.pos = saved_pos + + parse_cost_equation(source, constraints) + +def parse_cost_constraint(source, constraints): + "Parses a cost constraint." + saved_pos = source.pos + ch = source.get() + if ch in ALPHA: + # Syntax: constraint [("<=" | "<") cost] + constraint = parse_constraint(source, constraints, ch) + + max_inc = parse_fuzzy_compare(source) + + if max_inc is None: + # No maximum cost. + constraints[constraint] = 0, None + else: + # There's a maximum cost. + cost_pos = source.pos + max_cost = parse_cost_limit(source) + + # Inclusive or exclusive limit? + if not max_inc: + max_cost -= 1 + + if max_cost < 0: + raise error("bad fuzzy cost limit", source.string, cost_pos) + + constraints[constraint] = 0, max_cost + elif ch in DIGITS: + # Syntax: cost ("<=" | "<") constraint ("<=" | "<") cost + source.pos = saved_pos + + # Minimum cost. + cost_pos = source.pos + min_cost = parse_cost_limit(source) + + min_inc = parse_fuzzy_compare(source) + if min_inc is None: + raise ParseError() + + constraint = parse_constraint(source, constraints, source.get()) + + max_inc = parse_fuzzy_compare(source) + if max_inc is None: + raise ParseError() + + # Maximum cost. + cost_pos = source.pos + max_cost = parse_cost_limit(source) + + # Inclusive or exclusive limits? + if not min_inc: + min_cost += 1 + if not max_inc: + max_cost -= 1 + + if not 0 <= min_cost <= max_cost: + raise error("bad fuzzy cost limit", source.string, cost_pos) + + constraints[constraint] = min_cost, max_cost + else: + raise ParseError() + +def parse_cost_limit(source): + "Parses a cost limit." + cost_pos = source.pos + digits = parse_count(source) + + try: + return int(digits) + except ValueError: + pass + + raise error("bad fuzzy cost limit", source.string, cost_pos) + +def parse_constraint(source, constraints, ch): + "Parses a constraint." + if ch not in "deis": + raise ParseError() + + if ch in constraints: + raise ParseError() + + return ch + +def parse_fuzzy_compare(source): + "Parses a cost comparator." + if source.match("<="): + return True + elif source.match("<"): + return False + else: + return None + +def parse_cost_equation(source, constraints): + "Parses a cost equation." + if "cost" in constraints: + raise error("more than one cost equation", source.string, source.pos) + + cost = {} + + parse_cost_term(source, cost) + while source.match("+"): + parse_cost_term(source, cost) + + max_inc = parse_fuzzy_compare(source) + if max_inc is None: + raise ParseError() + + max_cost = int(parse_count(source)) + + if not max_inc: + max_cost -= 1 + + if max_cost < 0: + raise error("bad fuzzy cost limit", source.string, source.pos) + + cost["max"] = max_cost + + constraints["cost"] = cost + +def parse_cost_term(source, cost): + "Parses a cost equation term." + coeff = parse_count(source) + ch = source.get() + if ch not in "dis": + raise ParseError() + + if ch in cost: + raise error("repeated fuzzy cost", source.string, source.pos) + + cost[ch] = int(coeff or 1) + +def parse_fuzzy_test(source, info, case_flags): + saved_pos = source.pos + ch = source.get() + if ch in SPECIAL_CHARS: + if ch == "\\": + # An escape sequence outside a set. + return parse_escape(source, info, False) + elif ch == ".": + # Any character. + if info.flags & DOTALL: + return AnyAll() + elif info.flags & WORD: + return AnyU() + else: + return Any() + elif ch == "[": + # A character set. + return parse_set(source, info) + else: + raise error("expected character set", source.string, saved_pos) + elif ch: + # A literal. + return Character(ord(ch), case_flags=case_flags) + else: + raise error("expected character set", source.string, saved_pos) + +def parse_count(source): + "Parses a quantifier's count, which can be empty." + return source.get_while(DIGITS) + +def parse_paren(source, info): + """Parses a parenthesised subpattern or a flag. Returns FLAGS if it's an + inline flag. + """ + saved_pos = source.pos + ch = source.get(True) + if ch == "?": + # (?... + saved_pos_2 = source.pos + ch = source.get(True) + if ch == "<": + # (?<... + saved_pos_3 = source.pos + ch = source.get() + if ch in ("=", "!"): + # (?<=... or (?") + saved_flags = info.flags + try: + subpattern = _parse_pattern(source, info) + source.expect(")") + finally: + info.flags = saved_flags + source.ignore_space = bool(info.flags & VERBOSE) + + info.close_group() + return Group(info, group, subpattern) + if ch in ("=", "!"): + # (?=... or (?!...: lookahead. + return parse_lookaround(source, info, False, ch == "=") + if ch == "P": + # (?P...: a Python extension. + return parse_extension(source, info) + if ch == "#": + # (?#...: a comment. + return parse_comment(source) + if ch == "(": + # (?(...: a conditional subpattern. + return parse_conditional(source, info) + if ch == ">": + # (?>...: an atomic subpattern. + return parse_atomic(source, info) + if ch == "|": + # (?|...: a common/reset groups branch. + return parse_common(source, info) + if ch == "R" or "0" <= ch <= "9": + # (?R...: probably a call to a group. + return parse_call_group(source, info, ch, saved_pos_2) + if ch == "&": + # (?&...: a call to a named group. + return parse_call_named_group(source, info, saved_pos_2) + + # (?...: probably a flags subpattern. + source.pos = saved_pos_2 + return parse_flags_subpattern(source, info) + + if ch == "*": + # (*... + saved_pos_2 = source.pos + word = source.get_while(set(")>"), include=False) + if word[ : 1].isalpha(): + verb = VERBS.get(word) + if not verb: + raise error("unknown verb", source.string, saved_pos_2) + + source.expect(")") + + return verb + + # (...: an unnamed capture group. + source.pos = saved_pos + group = info.open_group() + saved_flags = info.flags + try: + subpattern = _parse_pattern(source, info) + source.expect(")") + finally: + info.flags = saved_flags + source.ignore_space = bool(info.flags & VERBOSE) + + info.close_group() + + return Group(info, group, subpattern) + +def parse_extension(source, info): + "Parses a Python extension." + saved_pos = source.pos + ch = source.get() + if ch == "<": + # (?P<...: a named capture group. + name = parse_name(source) + group = info.open_group(name) + source.expect(">") + saved_flags = info.flags + try: + subpattern = _parse_pattern(source, info) + source.expect(")") + finally: + info.flags = saved_flags + source.ignore_space = bool(info.flags & VERBOSE) + + info.close_group() + + return Group(info, group, subpattern) + if ch == "=": + # (?P=...: a named group reference. + name = parse_name(source, allow_numeric=True) + source.expect(")") + if info.is_open_group(name): + raise error("cannot refer to an open group", source.string, + saved_pos) + + return make_ref_group(info, name, saved_pos) + if ch == ">" or ch == "&": + # (?P>...: a call to a group. + return parse_call_named_group(source, info, saved_pos) + + source.pos = saved_pos + raise error("unknown extension", source.string, saved_pos) + +def parse_comment(source): + "Parses a comment." + while True: + saved_pos = source.pos + c = source.get(True) + + if not c or c == ")": + break + + if c == "\\": + c = source.get(True) + + source.pos = saved_pos + source.expect(")") + + return None + +def parse_lookaround(source, info, behind, positive): + "Parses a lookaround." + saved_flags = info.flags + try: + subpattern = _parse_pattern(source, info) + source.expect(")") + finally: + info.flags = saved_flags + source.ignore_space = bool(info.flags & VERBOSE) + + return LookAround(behind, positive, subpattern) + +def parse_conditional(source, info): + "Parses a conditional subpattern." + saved_flags = info.flags + saved_pos = source.pos + ch = source.get() + if ch == "?": + # (?(?... + ch = source.get() + if ch in ("=", "!"): + # (?(?=... or (?(?!...: lookahead conditional. + return parse_lookaround_conditional(source, info, False, ch == "=") + if ch == "<": + # (?(?<... + ch = source.get() + if ch in ("=", "!"): + # (?(?<=... or (?(?"), include=False) + + if not name: + raise error("missing group name", source.string, source.pos) + + if name.isdigit(): + min_group = 0 if allow_group_0 else 1 + if not allow_numeric or int(name) < min_group: + raise error("bad character in group name", source.string, + source.pos) + else: + if not name.isidentifier(): + raise error("bad character in group name", source.string, + source.pos) + + return name + +def is_octal(string): + "Checks whether a string is octal." + return all(ch in OCT_DIGITS for ch in string) + +def is_decimal(string): + "Checks whether a string is decimal." + return all(ch in DIGITS for ch in string) + +def is_hexadecimal(string): + "Checks whether a string is hexadecimal." + return all(ch in HEX_DIGITS for ch in string) + +def parse_escape(source, info, in_set): + "Parses an escape sequence." + saved_ignore = source.ignore_space + source.ignore_space = False + ch = source.get() + source.ignore_space = saved_ignore + if not ch: + # A backslash at the end of the pattern. + raise error("bad escape (end of pattern)", source.string, source.pos) + if ch in HEX_ESCAPES: + # A hexadecimal escape sequence. + return parse_hex_escape(source, info, ch, HEX_ESCAPES[ch], in_set, ch) + elif ch == "g" and not in_set: + # A group reference. + saved_pos = source.pos + try: + return parse_group_ref(source, info) + except error: + # Invalid as a group reference, so assume it's a literal. + source.pos = saved_pos + + return make_character(info, ord(ch), in_set) + elif ch == "G" and not in_set: + # A search anchor. + return SearchAnchor() + elif ch == "L" and not in_set: + # A string set. + return parse_string_set(source, info) + elif ch == "N": + # A named codepoint. + return parse_named_char(source, info, in_set) + elif ch in "pP": + # A Unicode property, positive or negative. + return parse_property(source, info, ch == "p", in_set) + elif ch == "R" and not in_set: + # A line ending. + charset = [0x0A, 0x0B, 0x0C, 0x0D] + if info.guess_encoding == UNICODE: + charset.extend([0x85, 0x2028, 0x2029]) + + return Atomic(Branch([String([0x0D, 0x0A]), SetUnion(info, [Character(c) + for c in charset])])) + elif ch == "X" and not in_set: + # A grapheme cluster. + return Grapheme() + elif ch in ALPHA: + # An alphabetic escape sequence. + # Positional escapes aren't allowed inside a character set. + if not in_set: + if info.flags & WORD: + value = WORD_POSITION_ESCAPES.get(ch) + else: + value = POSITION_ESCAPES.get(ch) + + if value: + return value + + value = CHARSET_ESCAPES.get(ch) + if value: + return value + + value = CHARACTER_ESCAPES.get(ch) + if value: + return Character(ord(value)) + + raise error("bad escape \\%s" % ch, source.string, source.pos) + elif ch in DIGITS: + # A numeric escape sequence. + return parse_numeric_escape(source, info, ch, in_set) + else: + # A literal. + return make_character(info, ord(ch), in_set) + +def parse_numeric_escape(source, info, ch, in_set): + "Parses a numeric escape sequence." + if in_set or ch == "0": + # Octal escape sequence, max 3 digits. + return parse_octal_escape(source, info, [ch], in_set) + + # At least 1 digit, so either octal escape or group. + digits = ch + saved_pos = source.pos + ch = source.get() + if ch in DIGITS: + # At least 2 digits, so either octal escape or group. + digits += ch + saved_pos = source.pos + ch = source.get() + if is_octal(digits) and ch in OCT_DIGITS: + # 3 octal digits, so octal escape sequence. + encoding = info.flags & _ALL_ENCODINGS + if encoding == ASCII or encoding == LOCALE: + octal_mask = 0xFF + else: + octal_mask = 0x1FF + + value = int(digits + ch, 8) & octal_mask + return make_character(info, value) + + # Group reference. + source.pos = saved_pos + if info.is_open_group(digits): + raise error("cannot refer to an open group", source.string, source.pos) + + return make_ref_group(info, digits, source.pos) + +def parse_octal_escape(source, info, digits, in_set): + "Parses an octal escape sequence." + saved_pos = source.pos + ch = source.get() + while len(digits) < 3 and ch in OCT_DIGITS: + digits.append(ch) + saved_pos = source.pos + ch = source.get() + + source.pos = saved_pos + try: + value = int("".join(digits), 8) + return make_character(info, value, in_set) + except ValueError: + if digits[0] in OCT_DIGITS: + raise error("incomplete escape \\%s" % ''.join(digits), + source.string, source.pos) + else: + raise error("bad escape \\%s" % digits[0], source.string, + source.pos) + +def parse_hex_escape(source, info, esc, expected_len, in_set, type): + "Parses a hex escape sequence." + saved_pos = source.pos + digits = [] + for i in range(expected_len): + ch = source.get() + if ch not in HEX_DIGITS: + raise error("incomplete escape \\%s%s" % (type, ''.join(digits)), + source.string, saved_pos) + digits.append(ch) + + try: + value = int("".join(digits), 16) + except ValueError: + pass + else: + if value < 0x110000: + return make_character(info, value, in_set) + + # Bad hex escape. + raise error("bad hex escape \\%s%s" % (esc, ''.join(digits)), + source.string, saved_pos) + +def parse_group_ref(source, info): + "Parses a group reference." + source.expect("<") + saved_pos = source.pos + name = parse_name(source, True) + source.expect(">") + if info.is_open_group(name): + raise error("cannot refer to an open group", source.string, source.pos) + + return make_ref_group(info, name, saved_pos) + +def parse_string_set(source, info): + "Parses a string set reference." + source.expect("<") + name = parse_name(source, True) + source.expect(">") + if name is None or name not in info.kwargs: + raise error("undefined named list", source.string, source.pos) + + return make_string_set(info, name) + +def parse_named_char(source, info, in_set): + "Parses a named character." + saved_pos = source.pos + if source.match("{"): + name = source.get_while(NAMED_CHAR_PART, keep_spaces=True) + if source.match("}"): + try: + value = unicodedata.lookup(name) + return make_character(info, ord(value), in_set) + except KeyError: + raise error("undefined character name", source.string, + source.pos) + + source.pos = saved_pos + return make_character(info, ord("N"), in_set) + +def parse_property(source, info, positive, in_set): + "Parses a Unicode property." + saved_pos = source.pos + ch = source.get() + if ch == "{": + negate = source.match("^") + prop_name, name = parse_property_name(source) + if source.match("}"): + # It's correctly delimited. + prop = lookup_property(prop_name, name, positive != negate, source) + return make_property(info, prop, in_set) + elif ch and ch in "CLMNPSZ": + # An abbreviated property, eg \pL. + prop = lookup_property(None, ch, positive, source) + return make_property(info, prop, in_set) + + # Not a property, so treat as a literal "p" or "P". + source.pos = saved_pos + ch = "p" if positive else "P" + return make_character(info, ord(ch), in_set) + +def parse_property_name(source): + "Parses a property name, which may be qualified." + name = source.get_while(PROPERTY_NAME_PART) + saved_pos = source.pos + + ch = source.get() + if ch and ch in ":=": + prop_name = name + name = source.get_while(ALNUM | set(" &_-./")).strip() + + if name: + # Name after the ":" or "=", so it's a qualified name. + saved_pos = source.pos + else: + # No name after the ":" or "=", so assume it's an unqualified name. + prop_name, name = None, prop_name + else: + prop_name = None + + source.pos = saved_pos + return prop_name, name + +def parse_set(source, info): + "Parses a character set." + version = (info.flags & _ALL_VERSIONS) or DEFAULT_VERSION + + saved_ignore = source.ignore_space + source.ignore_space = False + # Negative set? + negate = source.match("^") + try: + if version == VERSION0: + item = parse_set_imp_union(source, info) + else: + item = parse_set_union(source, info) + + if not source.match("]"): + raise error("missing ]", source.string, source.pos) + finally: + source.ignore_space = saved_ignore + + if negate: + item = item.with_flags(positive=not item.positive) + + item = item.with_flags(case_flags=make_case_flags(info)) + + return item + +def parse_set_union(source, info): + "Parses a set union ([x||y])." + items = [parse_set_symm_diff(source, info)] + while source.match("||"): + items.append(parse_set_symm_diff(source, info)) + + if len(items) == 1: + return items[0] + return SetUnion(info, items) + +def parse_set_symm_diff(source, info): + "Parses a set symmetric difference ([x~~y])." + items = [parse_set_inter(source, info)] + while source.match("~~"): + items.append(parse_set_inter(source, info)) + + if len(items) == 1: + return items[0] + return SetSymDiff(info, items) + +def parse_set_inter(source, info): + "Parses a set intersection ([x&&y])." + items = [parse_set_diff(source, info)] + while source.match("&&"): + items.append(parse_set_diff(source, info)) + + if len(items) == 1: + return items[0] + return SetInter(info, items) + +def parse_set_diff(source, info): + "Parses a set difference ([x--y])." + items = [parse_set_imp_union(source, info)] + while source.match("--"): + items.append(parse_set_imp_union(source, info)) + + if len(items) == 1: + return items[0] + return SetDiff(info, items) + +def parse_set_imp_union(source, info): + "Parses a set implicit union ([xy])." + version = (info.flags & _ALL_VERSIONS) or DEFAULT_VERSION + + items = [parse_set_member(source, info)] + while True: + saved_pos = source.pos + if source.match("]"): + # End of the set. + source.pos = saved_pos + break + + if version == VERSION1 and any(source.match(op) for op in SET_OPS): + # The new behaviour has set operators. + source.pos = saved_pos + break + + items.append(parse_set_member(source, info)) + + if len(items) == 1: + return items[0] + return SetUnion(info, items) + +def parse_set_member(source, info): + "Parses a member in a character set." + # Parse a set item. + start = parse_set_item(source, info) + saved_pos1 = source.pos + if (not isinstance(start, Character) or not start.positive or not + source.match("-")): + # It's not the start of a range. + return start + + version = (info.flags & _ALL_VERSIONS) or DEFAULT_VERSION + + # It looks like the start of a range of characters. + saved_pos2 = source.pos + if version == VERSION1 and source.match("-"): + # It's actually the set difference operator '--', so return the + # character. + source.pos = saved_pos1 + return start + + if source.match("]"): + # We've reached the end of the set, so return both the character and + # hyphen. + source.pos = saved_pos2 + return SetUnion(info, [start, Character(ord("-"))]) + + # Parse a set item. + end = parse_set_item(source, info) + if not isinstance(end, Character) or not end.positive: + # It's not a range, so return the character, hyphen and property. + return SetUnion(info, [start, Character(ord("-")), end]) + + # It _is_ a range. + if start.value > end.value: + raise error("bad character range", source.string, source.pos) + + if start.value == end.value: + return start + + return Range(start.value, end.value) + +def parse_set_item(source, info): + "Parses an item in a character set." + version = (info.flags & _ALL_VERSIONS) or DEFAULT_VERSION + + if source.match("\\"): + # An escape sequence in a set. + return parse_escape(source, info, True) + + saved_pos = source.pos + if source.match("[:"): + # Looks like a POSIX character class. + try: + return parse_posix_class(source, info) + except ParseError: + # Not a POSIX character class. + source.pos = saved_pos + + if version == VERSION1 and source.match("["): + # It's the start of a nested set. + + # Negative set? + negate = source.match("^") + item = parse_set_union(source, info) + + if not source.match("]"): + raise error("missing ]", source.string, source.pos) + + if negate: + item = item.with_flags(positive=not item.positive) + + return item + + ch = source.get() + if not ch: + raise error("unterminated character set", source.string, source.pos) + + return Character(ord(ch)) + +def parse_posix_class(source, info): + "Parses a POSIX character class." + negate = source.match("^") + prop_name, name = parse_property_name(source) + if not source.match(":]"): + raise ParseError() + + return lookup_property(prop_name, name, not negate, source, posix=True) + +def float_to_rational(flt): + "Converts a float to a rational pair." + int_part = int(flt) + error = flt - int_part + if abs(error) < 0.0001: + return int_part, 1 + + den, num = float_to_rational(1.0 / error) + + return int_part * den + num, den + +def numeric_to_rational(numeric): + "Converts a numeric string to a rational string, if possible." + if numeric[ : 1] == "-": + sign, numeric = numeric[0], numeric[1 : ] + else: + sign = "" + + parts = numeric.split("/") + if len(parts) == 2: + num, den = float_to_rational(float(parts[0]) / float(parts[1])) + elif len(parts) == 1: + num, den = float_to_rational(float(parts[0])) + else: + raise ValueError() + + result = "{}{}/{}".format(sign, num, den) + if result.endswith("/1"): + return result[ : -2] + + return result + +def standardise_name(name): + "Standardises a property or value name." + try: + return numeric_to_rational("".join(name)) + except (ValueError, ZeroDivisionError): + return "".join(ch for ch in name if ch not in "_- ").upper() + +_POSIX_CLASSES = set('ALNUM DIGIT PUNCT XDIGIT'.split()) + +_BINARY_VALUES = set('YES Y NO N TRUE T FALSE F'.split()) + +def lookup_property(property, value, positive, source=None, posix=False): + "Looks up a property." + # Normalise the names (which may still be lists). + property = standardise_name(property) if property else None + value = standardise_name(value) + + if (property, value) == ("GENERALCATEGORY", "ASSIGNED"): + property, value, positive = "GENERALCATEGORY", "UNASSIGNED", not positive + + if posix and not property and value.upper() in _POSIX_CLASSES: + value = 'POSIX' + value + + if property: + # Both the property and the value are provided. + prop = PROPERTIES.get(property) + if not prop: + if not source: + raise error("unknown property") + + raise error("unknown property", source.string, source.pos) + + prop_id, value_dict = prop + val_id = value_dict.get(value) + if val_id is None: + if not source: + raise error("unknown property value") + + raise error("unknown property value", source.string, source.pos) + + return Property((prop_id << 16) | val_id, positive) + + # Only the value is provided. + # It might be the name of a GC, script or block value. + for property in ("GC", "SCRIPT", "BLOCK"): + prop_id, value_dict = PROPERTIES.get(property) + val_id = value_dict.get(value) + if val_id is not None: + return Property((prop_id << 16) | val_id, positive) + + # It might be the name of a binary property. + prop = PROPERTIES.get(value) + if prop: + prop_id, value_dict = prop + if set(value_dict) == _BINARY_VALUES: + return Property((prop_id << 16) | 1, positive) + + return Property(prop_id << 16, not positive) + + # It might be the name of a binary property starting with a prefix. + if value.startswith("IS"): + prop = PROPERTIES.get(value[2 : ]) + if prop: + prop_id, value_dict = prop + if "YES" in value_dict: + return Property((prop_id << 16) | 1, positive) + + # It might be the name of a script or block starting with a prefix. + for prefix, property in (("IS", "SCRIPT"), ("IN", "BLOCK")): + if value.startswith(prefix): + prop_id, value_dict = PROPERTIES.get(property) + val_id = value_dict.get(value[2 : ]) + if val_id is not None: + return Property((prop_id << 16) | val_id, positive) + + # Unknown property. + if not source: + raise error("unknown property") + + raise error("unknown property", source.string, source.pos) + +def _compile_replacement(source, pattern, is_unicode): + "Compiles a replacement template escape sequence." + ch = source.get() + if ch in ALPHA: + # An alphabetic escape sequence. + value = CHARACTER_ESCAPES.get(ch) + if value: + return False, [ord(value)] + + if ch in HEX_ESCAPES and (ch == "x" or is_unicode): + # A hexadecimal escape sequence. + return False, [parse_repl_hex_escape(source, HEX_ESCAPES[ch], ch)] + + if ch == "g": + # A group preference. + return True, [compile_repl_group(source, pattern)] + + if ch == "N" and is_unicode: + # A named character. + value = parse_repl_named_char(source) + if value is not None: + return False, [value] + + raise error("bad escape \\%s" % ch, source.string, source.pos) + + if isinstance(source.sep, bytes): + octal_mask = 0xFF + else: + octal_mask = 0x1FF + + if ch == "0": + # An octal escape sequence. + digits = ch + while len(digits) < 3: + saved_pos = source.pos + ch = source.get() + if ch not in OCT_DIGITS: + source.pos = saved_pos + break + digits += ch + + return False, [int(digits, 8) & octal_mask] + + if ch in DIGITS: + # Either an octal escape sequence (3 digits) or a group reference (max + # 2 digits). + digits = ch + saved_pos = source.pos + ch = source.get() + if ch in DIGITS: + digits += ch + saved_pos = source.pos + ch = source.get() + if ch and is_octal(digits + ch): + # An octal escape sequence. + return False, [int(digits + ch, 8) & octal_mask] + + # A group reference. + source.pos = saved_pos + return True, [int(digits)] + + if ch == "\\": + # An escaped backslash is a backslash. + return False, [ord("\\")] + + if not ch: + # A trailing backslash. + raise error("bad escape (end of pattern)", source.string, source.pos) + + # An escaped non-backslash is a backslash followed by the literal. + return False, [ord("\\"), ord(ch)] + +def parse_repl_hex_escape(source, expected_len, type): + "Parses a hex escape sequence in a replacement string." + digits = [] + for i in range(expected_len): + ch = source.get() + if ch not in HEX_DIGITS: + raise error("incomplete escape \\%s%s" % (type, ''.join(digits)), + source.string, source.pos) + digits.append(ch) + + return int("".join(digits), 16) + +def parse_repl_named_char(source): + "Parses a named character in a replacement string." + saved_pos = source.pos + if source.match("{"): + name = source.get_while(ALPHA | set(" ")) + + if source.match("}"): + try: + value = unicodedata.lookup(name) + return ord(value) + except KeyError: + raise error("undefined character name", source.string, + source.pos) + + source.pos = saved_pos + return None + +def compile_repl_group(source, pattern): + "Compiles a replacement template group reference." + source.expect("<") + name = parse_name(source, True, True) + + source.expect(">") + if name.isdigit(): + index = int(name) + if not 0 <= index <= pattern.groups: + raise error("invalid group reference", source.string, source.pos) + + return index + + try: + return pattern.groupindex[name] + except KeyError: + raise IndexError("unknown group") + +# The regular expression is parsed into a syntax tree. The different types of +# node are defined below. + +INDENT = " " +POSITIVE_OP = 0x1 +ZEROWIDTH_OP = 0x2 +FUZZY_OP = 0x4 +REVERSE_OP = 0x8 +REQUIRED_OP = 0x10 + +POS_TEXT = {False: "NON-MATCH", True: "MATCH"} +CASE_TEXT = {NOCASE: "", IGNORECASE: " SIMPLE_IGNORE_CASE", FULLCASE: "", + FULLIGNORECASE: " FULL_IGNORE_CASE"} + +def make_sequence(items): + if len(items) == 1: + return items[0] + return Sequence(items) + +# Common base class for all nodes. +class RegexBase: + def __init__(self): + self._key = self.__class__ + + def with_flags(self, positive=None, case_flags=None, zerowidth=None): + if positive is None: + positive = self.positive + else: + positive = bool(positive) + if case_flags is None: + case_flags = self.case_flags + else: + case_flags = CASE_FLAGS_COMBINATIONS[case_flags & CASE_FLAGS] + if zerowidth is None: + zerowidth = self.zerowidth + else: + zerowidth = bool(zerowidth) + + if (positive == self.positive and case_flags == self.case_flags and + zerowidth == self.zerowidth): + return self + + return self.rebuild(positive, case_flags, zerowidth) + + def fix_groups(self, pattern, reverse, fuzzy): + pass + + def optimise(self, info, reverse): + return self + + def pack_characters(self, info): + return self + + def remove_captures(self): + return self + + def is_atomic(self): + return True + + def can_be_affix(self): + return True + + def contains_group(self): + return False + + def get_firstset(self, reverse): + raise _FirstSetError() + + def has_simple_start(self): + return False + + def compile(self, reverse=False, fuzzy=False): + return self._compile(reverse, fuzzy) + + def is_empty(self): + return False + + def __hash__(self): + return hash(self._key) + + def __eq__(self, other): + return type(self) is type(other) and self._key == other._key + + def __ne__(self, other): + return not self.__eq__(other) + + def get_required_string(self, reverse): + return self.max_width(), None + +# Base class for zero-width nodes. +class ZeroWidthBase(RegexBase): + def __init__(self, positive=True): + RegexBase.__init__(self) + self.positive = bool(positive) + + self._key = self.__class__, self.positive + + def get_firstset(self, reverse): + return set([None]) + + def _compile(self, reverse, fuzzy): + flags = 0 + if self.positive: + flags |= POSITIVE_OP + if fuzzy: + flags |= FUZZY_OP + if reverse: + flags |= REVERSE_OP + return [(self._opcode, flags)] + + def dump(self, indent, reverse): + print("{}{} {}".format(INDENT * indent, self._op_name, + POS_TEXT[self.positive])) + + def max_width(self): + return 0 + +class Any(RegexBase): + _opcode = {False: OP.ANY, True: OP.ANY_REV} + _op_name = "ANY" + + def has_simple_start(self): + return True + + def _compile(self, reverse, fuzzy): + flags = 0 + if fuzzy: + flags |= FUZZY_OP + return [(self._opcode[reverse], flags)] + + def dump(self, indent, reverse): + print("{}{}".format(INDENT * indent, self._op_name)) + + def max_width(self): + return 1 + +class AnyAll(Any): + _opcode = {False: OP.ANY_ALL, True: OP.ANY_ALL_REV} + _op_name = "ANY_ALL" + +class AnyU(Any): + _opcode = {False: OP.ANY_U, True: OP.ANY_U_REV} + _op_name = "ANY_U" + +class Atomic(RegexBase): + def __init__(self, subpattern): + RegexBase.__init__(self) + self.subpattern = subpattern + + def fix_groups(self, pattern, reverse, fuzzy): + self.subpattern.fix_groups(pattern, reverse, fuzzy) + + def optimise(self, info, reverse): + self.subpattern = self.subpattern.optimise(info, reverse) + + if self.subpattern.is_empty(): + return self.subpattern + return self + + def pack_characters(self, info): + self.subpattern = self.subpattern.pack_characters(info) + return self + + def remove_captures(self): + self.subpattern = self.subpattern.remove_captures() + return self + + def can_be_affix(self): + return self.subpattern.can_be_affix() + + def contains_group(self): + return self.subpattern.contains_group() + + def get_firstset(self, reverse): + return self.subpattern.get_firstset(reverse) + + def has_simple_start(self): + return self.subpattern.has_simple_start() + + def _compile(self, reverse, fuzzy): + return ([(OP.ATOMIC, )] + self.subpattern.compile(reverse, fuzzy) + + [(OP.END, )]) + + def dump(self, indent, reverse): + print("{}ATOMIC".format(INDENT * indent)) + self.subpattern.dump(indent + 1, reverse) + + def is_empty(self): + return self.subpattern.is_empty() + + def __eq__(self, other): + return (type(self) is type(other) and self.subpattern == + other.subpattern) + + def max_width(self): + return self.subpattern.max_width() + + def get_required_string(self, reverse): + return self.subpattern.get_required_string(reverse) + +class Boundary(ZeroWidthBase): + _opcode = OP.BOUNDARY + _op_name = "BOUNDARY" + +class Branch(RegexBase): + def __init__(self, branches): + RegexBase.__init__(self) + self.branches = branches + + def fix_groups(self, pattern, reverse, fuzzy): + for b in self.branches: + b.fix_groups(pattern, reverse, fuzzy) + + def optimise(self, info, reverse): + if not self.branches: + return Sequence([]) + + # Flatten branches within branches. + branches = Branch._flatten_branches(info, reverse, self.branches) + + # Move any common prefix or suffix out of the branches. + if reverse: + suffix, branches = Branch._split_common_suffix(info, branches) + prefix = [] + else: + prefix, branches = Branch._split_common_prefix(info, branches) + suffix = [] + + # Try to reduce adjacent single-character branches to sets. + branches = Branch._reduce_to_set(info, reverse, branches) + + if len(branches) > 1: + sequence = [Branch(branches)] + + if not prefix or not suffix: + # We might be able to add a quick precheck before the branches. + firstset = self._add_precheck(info, reverse, branches) + + if firstset: + if reverse: + sequence.append(firstset) + else: + sequence.insert(0, firstset) + else: + sequence = branches + + return make_sequence(prefix + sequence + suffix) + + def _add_precheck(self, info, reverse, branches): + charset = set() + pos = -1 if reverse else 0 + + for branch in branches: + if type(branch) is Literal and branch.case_flags == NOCASE: + charset.add(branch.characters[pos]) + else: + return + + if not charset: + return None + + return _check_firstset(info, reverse, [Character(c) for c in charset]) + + def pack_characters(self, info): + self.branches = [b.pack_characters(info) for b in self.branches] + return self + + def remove_captures(self): + self.branches = [b.remove_captures() for b in self.branches] + return self + + def is_atomic(self): + return all(b.is_atomic() for b in self.branches) + + def can_be_affix(self): + return all(b.can_be_affix() for b in self.branches) + + def contains_group(self): + return any(b.contains_group() for b in self.branches) + + def get_firstset(self, reverse): + fs = set() + for b in self.branches: + fs |= b.get_firstset(reverse) + + return fs or set([None]) + + def _compile(self, reverse, fuzzy): + if not self.branches: + return [] + + code = [(OP.BRANCH, )] + for b in self.branches: + code.extend(b.compile(reverse, fuzzy)) + code.append((OP.NEXT, )) + + code[-1] = (OP.END, ) + + return code + + def dump(self, indent, reverse): + print("{}BRANCH".format(INDENT * indent)) + self.branches[0].dump(indent + 1, reverse) + for b in self.branches[1 : ]: + print("{}OR".format(INDENT * indent)) + b.dump(indent + 1, reverse) + + @staticmethod + def _flatten_branches(info, reverse, branches): + # Flatten the branches so that there aren't branches of branches. + new_branches = [] + for b in branches: + b = b.optimise(info, reverse) + if isinstance(b, Branch): + new_branches.extend(b.branches) + else: + new_branches.append(b) + + return new_branches + + @staticmethod + def _split_common_prefix(info, branches): + # Common leading items can be moved out of the branches. + # Get the items in the branches. + alternatives = [] + for b in branches: + if isinstance(b, Sequence): + alternatives.append(b.items) + else: + alternatives.append([b]) + + # What is the maximum possible length of the prefix? + max_count = min(len(a) for a in alternatives) + + # What is the longest common prefix? + prefix = alternatives[0] + pos = 0 + end_pos = max_count + while pos < end_pos and prefix[pos].can_be_affix() and all(a[pos] == + prefix[pos] for a in alternatives): + pos += 1 + count = pos + + if info.flags & UNICODE: + # We need to check that we're not splitting a sequence of + # characters which could form part of full case-folding. + count = pos + while count > 0 and not all(Branch._can_split(a, count) for a in + alternatives): + count -= 1 + + # No common prefix is possible. + if count == 0: + return [], branches + + # Rebuild the branches. + new_branches = [] + for a in alternatives: + new_branches.append(make_sequence(a[count : ])) + + return prefix[ : count], new_branches + + @staticmethod + def _split_common_suffix(info, branches): + # Common trailing items can be moved out of the branches. + # Get the items in the branches. + alternatives = [] + for b in branches: + if isinstance(b, Sequence): + alternatives.append(b.items) + else: + alternatives.append([b]) + + # What is the maximum possible length of the suffix? + max_count = min(len(a) for a in alternatives) + + # What is the longest common suffix? + suffix = alternatives[0] + pos = -1 + end_pos = -1 - max_count + while pos > end_pos and suffix[pos].can_be_affix() and all(a[pos] == + suffix[pos] for a in alternatives): + pos -= 1 + count = -1 - pos + + if info.flags & UNICODE: + # We need to check that we're not splitting a sequence of + # characters which could form part of full case-folding. + while count > 0 and not all(Branch._can_split_rev(a, count) for a + in alternatives): + count -= 1 + + # No common suffix is possible. + if count == 0: + return [], branches + + # Rebuild the branches. + new_branches = [] + for a in alternatives: + new_branches.append(make_sequence(a[ : -count])) + + return suffix[-count : ], new_branches + + @staticmethod + def _can_split(items, count): + # Check the characters either side of the proposed split. + if not Branch._is_full_case(items, count - 1): + return True + + if not Branch._is_full_case(items, count): + return True + + # Check whether a 1-1 split would be OK. + if Branch._is_folded(items[count - 1 : count + 1]): + return False + + # Check whether a 1-2 split would be OK. + if (Branch._is_full_case(items, count + 2) and + Branch._is_folded(items[count - 1 : count + 2])): + return False + + # Check whether a 2-1 split would be OK. + if (Branch._is_full_case(items, count - 2) and + Branch._is_folded(items[count - 2 : count + 1])): + return False + + return True + + @staticmethod + def _can_split_rev(items, count): + end = len(items) + + # Check the characters either side of the proposed split. + if not Branch._is_full_case(items, end - count): + return True + + if not Branch._is_full_case(items, end - count - 1): + return True + + # Check whether a 1-1 split would be OK. + if Branch._is_folded(items[end - count - 1 : end - count + 1]): + return False + + # Check whether a 1-2 split would be OK. + if (Branch._is_full_case(items, end - count + 2) and + Branch._is_folded(items[end - count - 1 : end - count + 2])): + return False + + # Check whether a 2-1 split would be OK. + if (Branch._is_full_case(items, end - count - 2) and + Branch._is_folded(items[end - count - 2 : end - count + 1])): + return False + + return True + + @staticmethod + def _merge_common_prefixes(info, reverse, branches): + # Branches with the same case-sensitive character prefix can be grouped + # together if they are separated only by other branches with a + # character prefix. + prefixed = defaultdict(list) + order = {} + new_branches = [] + for b in branches: + if Branch._is_simple_character(b): + # Branch starts with a simple character. + prefixed[b.value].append([b]) + order.setdefault(b.value, len(order)) + elif (isinstance(b, Sequence) and b.items and + Branch._is_simple_character(b.items[0])): + # Branch starts with a simple character. + prefixed[b.items[0].value].append(b.items) + order.setdefault(b.items[0].value, len(order)) + else: + Branch._flush_char_prefix(info, reverse, prefixed, order, + new_branches) + + new_branches.append(b) + + Branch._flush_char_prefix(info, prefixed, order, new_branches) + + return new_branches + + @staticmethod + def _is_simple_character(c): + return isinstance(c, Character) and c.positive and not c.case_flags + + @staticmethod + def _reduce_to_set(info, reverse, branches): + # Can the branches be reduced to a set? + new_branches = [] + items = set() + case_flags = NOCASE + for b in branches: + if isinstance(b, (Character, Property, SetBase)): + # Branch starts with a single character. + if b.case_flags != case_flags: + # Different case sensitivity, so flush. + Branch._flush_set_members(info, reverse, items, case_flags, + new_branches) + + case_flags = b.case_flags + + items.add(b.with_flags(case_flags=NOCASE)) + else: + Branch._flush_set_members(info, reverse, items, case_flags, + new_branches) + + new_branches.append(b) + + Branch._flush_set_members(info, reverse, items, case_flags, + new_branches) + + return new_branches + + @staticmethod + def _flush_char_prefix(info, reverse, prefixed, order, new_branches): + # Flush the prefixed branches. + if not prefixed: + return + + for value, branches in sorted(prefixed.items(), key=lambda pair: + order[pair[0]]): + if len(branches) == 1: + new_branches.append(make_sequence(branches[0])) + else: + subbranches = [] + optional = False + for b in branches: + if len(b) > 1: + subbranches.append(make_sequence(b[1 : ])) + elif not optional: + subbranches.append(Sequence()) + optional = True + + sequence = Sequence([Character(value), Branch(subbranches)]) + new_branches.append(sequence.optimise(info, reverse)) + + prefixed.clear() + order.clear() + + @staticmethod + def _flush_set_members(info, reverse, items, case_flags, new_branches): + # Flush the set members. + if not items: + return + + if len(items) == 1: + item = list(items)[0] + else: + item = SetUnion(info, list(items)).optimise(info, reverse) + + new_branches.append(item.with_flags(case_flags=case_flags)) + + items.clear() + + @staticmethod + def _is_full_case(items, i): + if not 0 <= i < len(items): + return False + + item = items[i] + return (isinstance(item, Character) and item.positive and + (item.case_flags & FULLIGNORECASE) == FULLIGNORECASE) + + @staticmethod + def _is_folded(items): + if len(items) < 2: + return False + + for i in items: + if (not isinstance(i, Character) or not i.positive or not + i.case_flags): + return False + + folded = "".join(chr(i.value) for i in items) + folded = _regex.fold_case(FULL_CASE_FOLDING, folded) + + # Get the characters which expand to multiple codepoints on folding. + expanding_chars = _regex.get_expand_on_folding() + + for c in expanding_chars: + if folded == _regex.fold_case(FULL_CASE_FOLDING, c): + return True + + return False + + def is_empty(self): + return all(b.is_empty() for b in self.branches) + + def __eq__(self, other): + return type(self) is type(other) and self.branches == other.branches + + def max_width(self): + return max(b.max_width() for b in self.branches) + +class CallGroup(RegexBase): + def __init__(self, info, group, position): + RegexBase.__init__(self) + self.info = info + self.group = group + self.position = position + + self._key = self.__class__, self.group + + def fix_groups(self, pattern, reverse, fuzzy): + try: + self.group = int(self.group) + except ValueError: + try: + self.group = self.info.group_index[self.group] + except KeyError: + raise error("invalid group reference", pattern, self.position) + + if not 0 <= self.group <= self.info.group_count: + raise error("unknown group", pattern, self.position) + + if self.group > 0 and self.info.open_group_count[self.group] > 1: + raise error("ambiguous group reference", pattern, self.position) + + self.info.group_calls.append((self, reverse, fuzzy)) + + self._key = self.__class__, self.group + + def remove_captures(self): + raise error("group reference not allowed", pattern, self.position) + + def _compile(self, reverse, fuzzy): + return [(OP.GROUP_CALL, self.call_ref)] + + def dump(self, indent, reverse): + print("{}GROUP_CALL {}".format(INDENT * indent, self.group)) + + def __eq__(self, other): + return type(self) is type(other) and self.group == other.group + + def max_width(self): + return UNLIMITED + + def __del__(self): + self.info = None + +class CallRef(RegexBase): + def __init__(self, ref, parsed): + self.ref = ref + self.parsed = parsed + + def _compile(self, reverse, fuzzy): + return ([(OP.CALL_REF, self.ref)] + self.parsed._compile(reverse, + fuzzy) + [(OP.END, )]) + +class Character(RegexBase): + _opcode = {(NOCASE, False): OP.CHARACTER, (IGNORECASE, False): + OP.CHARACTER_IGN, (FULLCASE, False): OP.CHARACTER, (FULLIGNORECASE, + False): OP.CHARACTER_IGN, (NOCASE, True): OP.CHARACTER_REV, (IGNORECASE, + True): OP.CHARACTER_IGN_REV, (FULLCASE, True): OP.CHARACTER_REV, + (FULLIGNORECASE, True): OP.CHARACTER_IGN_REV} + + def __init__(self, value, positive=True, case_flags=NOCASE, + zerowidth=False): + RegexBase.__init__(self) + self.value = value + self.positive = bool(positive) + self.case_flags = CASE_FLAGS_COMBINATIONS[case_flags] + self.zerowidth = bool(zerowidth) + + if (self.positive and (self.case_flags & FULLIGNORECASE) == + FULLIGNORECASE): + self.folded = _regex.fold_case(FULL_CASE_FOLDING, chr(self.value)) + else: + self.folded = chr(self.value) + + self._key = (self.__class__, self.value, self.positive, + self.case_flags, self.zerowidth) + + def rebuild(self, positive, case_flags, zerowidth): + return Character(self.value, positive, case_flags, zerowidth) + + def optimise(self, info, reverse, in_set=False): + return self + + def get_firstset(self, reverse): + return set([self]) + + def has_simple_start(self): + return True + + def _compile(self, reverse, fuzzy): + flags = 0 + if self.positive: + flags |= POSITIVE_OP + if self.zerowidth: + flags |= ZEROWIDTH_OP + if fuzzy: + flags |= FUZZY_OP + + code = PrecompiledCode([self._opcode[self.case_flags, reverse], flags, + self.value]) + + if len(self.folded) > 1: + # The character expands on full case-folding. + code = Branch([code, String([ord(c) for c in self.folded], + case_flags=self.case_flags)]) + + return code.compile(reverse, fuzzy) + + def dump(self, indent, reverse): + display = ascii(chr(self.value)).lstrip("bu") + print("{}CHARACTER {} {}{}".format(INDENT * indent, + POS_TEXT[self.positive], display, CASE_TEXT[self.case_flags])) + + def matches(self, ch): + return (ch == self.value) == self.positive + + def max_width(self): + return len(self.folded) + + def get_required_string(self, reverse): + if not self.positive: + return 1, None + + self.folded_characters = tuple(ord(c) for c in self.folded) + + return 0, self + +class Conditional(RegexBase): + def __init__(self, info, group, yes_item, no_item, position): + RegexBase.__init__(self) + self.info = info + self.group = group + self.yes_item = yes_item + self.no_item = no_item + self.position = position + + def fix_groups(self, pattern, reverse, fuzzy): + try: + self.group = int(self.group) + except ValueError: + try: + self.group = self.info.group_index[self.group] + except KeyError: + if self.group == 'DEFINE': + # 'DEFINE' is a special name unless there's a group with + # that name. + self.group = 0 + else: + raise error("unknown group", pattern, self.position) + + if not 0 <= self.group <= self.info.group_count: + raise error("invalid group reference", pattern, self.position) + + self.yes_item.fix_groups(pattern, reverse, fuzzy) + self.no_item.fix_groups(pattern, reverse, fuzzy) + + def optimise(self, info, reverse): + yes_item = self.yes_item.optimise(info, reverse) + no_item = self.no_item.optimise(info, reverse) + + return Conditional(info, self.group, yes_item, no_item, self.position) + + def pack_characters(self, info): + self.yes_item = self.yes_item.pack_characters(info) + self.no_item = self.no_item.pack_characters(info) + return self + + def remove_captures(self): + self.yes_item = self.yes_item.remove_captures() + self.no_item = self.no_item.remove_captures() + + def is_atomic(self): + return self.yes_item.is_atomic() and self.no_item.is_atomic() + + def can_be_affix(self): + return self.yes_item.can_be_affix() and self.no_item.can_be_affix() + + def contains_group(self): + return self.yes_item.contains_group() or self.no_item.contains_group() + + def get_firstset(self, reverse): + return (self.yes_item.get_firstset(reverse) | + self.no_item.get_firstset(reverse)) + + def _compile(self, reverse, fuzzy): + code = [(OP.GROUP_EXISTS, self.group)] + code.extend(self.yes_item.compile(reverse, fuzzy)) + add_code = self.no_item.compile(reverse, fuzzy) + if add_code: + code.append((OP.NEXT, )) + code.extend(add_code) + + code.append((OP.END, )) + + return code + + def dump(self, indent, reverse): + print("{}GROUP_EXISTS {}".format(INDENT * indent, self.group)) + self.yes_item.dump(indent + 1, reverse) + if not self.no_item.is_empty(): + print("{}OR".format(INDENT * indent)) + self.no_item.dump(indent + 1, reverse) + + def is_empty(self): + return self.yes_item.is_empty() and self.no_item.is_empty() + + def __eq__(self, other): + return type(self) is type(other) and (self.group, self.yes_item, + self.no_item) == (other.group, other.yes_item, other.no_item) + + def max_width(self): + return max(self.yes_item.max_width(), self.no_item.max_width()) + + def __del__(self): + self.info = None + +class DefaultBoundary(ZeroWidthBase): + _opcode = OP.DEFAULT_BOUNDARY + _op_name = "DEFAULT_BOUNDARY" + +class DefaultEndOfWord(ZeroWidthBase): + _opcode = OP.DEFAULT_END_OF_WORD + _op_name = "DEFAULT_END_OF_WORD" + +class DefaultStartOfWord(ZeroWidthBase): + _opcode = OP.DEFAULT_START_OF_WORD + _op_name = "DEFAULT_START_OF_WORD" + +class EndOfLine(ZeroWidthBase): + _opcode = OP.END_OF_LINE + _op_name = "END_OF_LINE" + +class EndOfLineU(EndOfLine): + _opcode = OP.END_OF_LINE_U + _op_name = "END_OF_LINE_U" + +class EndOfString(ZeroWidthBase): + _opcode = OP.END_OF_STRING + _op_name = "END_OF_STRING" + +class EndOfStringLine(ZeroWidthBase): + _opcode = OP.END_OF_STRING_LINE + _op_name = "END_OF_STRING_LINE" + +class EndOfStringLineU(EndOfStringLine): + _opcode = OP.END_OF_STRING_LINE_U + _op_name = "END_OF_STRING_LINE_U" + +class EndOfWord(ZeroWidthBase): + _opcode = OP.END_OF_WORD + _op_name = "END_OF_WORD" + +class Failure(ZeroWidthBase): + _op_name = "FAILURE" + + def _compile(self, reverse, fuzzy): + return [(OP.FAILURE, )] + +class Fuzzy(RegexBase): + def __init__(self, subpattern, constraints=None): + RegexBase.__init__(self) + if constraints is None: + constraints = {} + self.subpattern = subpattern + self.constraints = constraints + + # If an error type is mentioned in the cost equation, then its maximum + # defaults to unlimited. + if "cost" in constraints: + for e in "dis": + if e in constraints["cost"]: + constraints.setdefault(e, (0, None)) + + # If any error type is mentioned, then all the error maxima default to + # 0, otherwise they default to unlimited. + if set(constraints) & set("dis"): + for e in "dis": + constraints.setdefault(e, (0, 0)) + else: + for e in "dis": + constraints.setdefault(e, (0, None)) + + # The maximum of the generic error type defaults to unlimited. + constraints.setdefault("e", (0, None)) + + # The cost equation defaults to equal costs. Also, the cost of any + # error type not mentioned in the cost equation defaults to 0. + if "cost" in constraints: + for e in "dis": + constraints["cost"].setdefault(e, 0) + else: + constraints["cost"] = {"d": 1, "i": 1, "s": 1, "max": + constraints["e"][1]} + + def fix_groups(self, pattern, reverse, fuzzy): + self.subpattern.fix_groups(pattern, reverse, True) + + def pack_characters(self, info): + self.subpattern = self.subpattern.pack_characters(info) + return self + + def remove_captures(self): + self.subpattern = self.subpattern.remove_captures() + return self + + def is_atomic(self): + return self.subpattern.is_atomic() + + def contains_group(self): + return self.subpattern.contains_group() + + def _compile(self, reverse, fuzzy): + # The individual limits. + arguments = [] + for e in "dise": + v = self.constraints[e] + arguments.append(v[0]) + arguments.append(UNLIMITED if v[1] is None else v[1]) + + # The coeffs of the cost equation. + for e in "dis": + arguments.append(self.constraints["cost"][e]) + + # The maximum of the cost equation. + v = self.constraints["cost"]["max"] + arguments.append(UNLIMITED if v is None else v) + + flags = 0 + if reverse: + flags |= REVERSE_OP + + test = self.constraints.get("test") + + if test: + return ([(OP.FUZZY_EXT, flags) + tuple(arguments)] + + test.compile(reverse, True) + [(OP.NEXT,)] + + self.subpattern.compile(reverse, True) + [(OP.END,)]) + + return ([(OP.FUZZY, flags) + tuple(arguments)] + + self.subpattern.compile(reverse, True) + [(OP.END,)]) + + def dump(self, indent, reverse): + constraints = self._constraints_to_string() + if constraints: + constraints = " " + constraints + print("{}FUZZY{}".format(INDENT * indent, constraints)) + self.subpattern.dump(indent + 1, reverse) + + def is_empty(self): + return self.subpattern.is_empty() + + def __eq__(self, other): + return (type(self) is type(other) and self.subpattern == + other.subpattern and self.constraints == other.constraints) + + def max_width(self): + return UNLIMITED + + def _constraints_to_string(self): + constraints = [] + + for name in "ids": + min, max = self.constraints[name] + if max == 0: + continue + + con = "" + + if min > 0: + con = "{}<=".format(min) + + con += name + + if max is not None: + con += "<={}".format(max) + + constraints.append(con) + + cost = [] + for name in "ids": + coeff = self.constraints["cost"][name] + if coeff > 0: + cost.append("{}{}".format(coeff, name)) + + limit = self.constraints["cost"]["max"] + if limit is not None and limit > 0: + cost = "{}<={}".format("+".join(cost), limit) + constraints.append(cost) + + return ",".join(constraints) + +class Grapheme(RegexBase): + def _compile(self, reverse, fuzzy): + # Match at least 1 character until a grapheme boundary is reached. Note + # that this is the same whether matching forwards or backwards. + grapheme_matcher = Atomic(Sequence([LazyRepeat(AnyAll(), 1, None), + GraphemeBoundary()])) + + return grapheme_matcher.compile(reverse, fuzzy) + + def dump(self, indent, reverse): + print("{}GRAPHEME".format(INDENT * indent)) + + def max_width(self): + return UNLIMITED + +class GraphemeBoundary: + def compile(self, reverse, fuzzy): + return [(OP.GRAPHEME_BOUNDARY, 1)] + +class GreedyRepeat(RegexBase): + _opcode = OP.GREEDY_REPEAT + _op_name = "GREEDY_REPEAT" + + def __init__(self, subpattern, min_count, max_count): + RegexBase.__init__(self) + self.subpattern = subpattern + self.min_count = min_count + self.max_count = max_count + + def fix_groups(self, pattern, reverse, fuzzy): + self.subpattern.fix_groups(pattern, reverse, fuzzy) + + def optimise(self, info, reverse): + subpattern = self.subpattern.optimise(info, reverse) + + return type(self)(subpattern, self.min_count, self.max_count) + + def pack_characters(self, info): + self.subpattern = self.subpattern.pack_characters(info) + return self + + def remove_captures(self): + self.subpattern = self.subpattern.remove_captures() + return self + + def is_atomic(self): + return self.min_count == self.max_count and self.subpattern.is_atomic() + + def can_be_affix(self): + return False + + def contains_group(self): + return self.subpattern.contains_group() + + def get_firstset(self, reverse): + fs = self.subpattern.get_firstset(reverse) + if self.min_count == 0: + fs.add(None) + + return fs + + def _compile(self, reverse, fuzzy): + repeat = [self._opcode, self.min_count] + if self.max_count is None: + repeat.append(UNLIMITED) + else: + repeat.append(self.max_count) + + subpattern = self.subpattern.compile(reverse, fuzzy) + if not subpattern: + return [] + + return ([tuple(repeat)] + subpattern + [(OP.END, )]) + + def dump(self, indent, reverse): + if self.max_count is None: + limit = "INF" + else: + limit = self.max_count + print("{}{} {} {}".format(INDENT * indent, self._op_name, + self.min_count, limit)) + + self.subpattern.dump(indent + 1, reverse) + + def is_empty(self): + return self.subpattern.is_empty() + + def __eq__(self, other): + return type(self) is type(other) and (self.subpattern, self.min_count, + self.max_count) == (other.subpattern, other.min_count, + other.max_count) + + def max_width(self): + if self.max_count is None: + return UNLIMITED + + return self.subpattern.max_width() * self.max_count + + def get_required_string(self, reverse): + max_count = UNLIMITED if self.max_count is None else self.max_count + if self.min_count == 0: + w = self.subpattern.max_width() * max_count + return min(w, UNLIMITED), None + + ofs, req = self.subpattern.get_required_string(reverse) + if req: + return ofs, req + + w = self.subpattern.max_width() * max_count + return min(w, UNLIMITED), None + +class PossessiveRepeat(GreedyRepeat): + def is_atomic(self): + return True + + def _compile(self, reverse, fuzzy): + subpattern = self.subpattern.compile(reverse, fuzzy) + if not subpattern: + return [] + + repeat = [self._opcode, self.min_count] + if self.max_count is None: + repeat.append(UNLIMITED) + else: + repeat.append(self.max_count) + + return ([(OP.ATOMIC, ), tuple(repeat)] + subpattern + [(OP.END, ), + (OP.END, )]) + + def dump(self, indent, reverse): + print("{}ATOMIC".format(INDENT * indent)) + + if self.max_count is None: + limit = "INF" + else: + limit = self.max_count + print("{}{} {} {}".format(INDENT * (indent + 1), self._op_name, + self.min_count, limit)) + + self.subpattern.dump(indent + 2, reverse) + +class Group(RegexBase): + def __init__(self, info, group, subpattern): + RegexBase.__init__(self) + self.info = info + self.group = group + self.subpattern = subpattern + + self.call_ref = None + + def fix_groups(self, pattern, reverse, fuzzy): + self.info.defined_groups[self.group] = (self, reverse, fuzzy) + self.subpattern.fix_groups(pattern, reverse, fuzzy) + + def optimise(self, info, reverse): + subpattern = self.subpattern.optimise(info, reverse) + + return Group(self.info, self.group, subpattern) + + def pack_characters(self, info): + self.subpattern = self.subpattern.pack_characters(info) + return self + + def remove_captures(self): + return self.subpattern.remove_captures() + + def is_atomic(self): + return self.subpattern.is_atomic() + + def can_be_affix(self): + return False + + def contains_group(self): + return True + + def get_firstset(self, reverse): + return self.subpattern.get_firstset(reverse) + + def has_simple_start(self): + return self.subpattern.has_simple_start() + + def _compile(self, reverse, fuzzy): + code = [] + + public_group = private_group = self.group + if private_group < 0: + public_group = self.info.private_groups[private_group] + private_group = self.info.group_count - private_group + + key = self.group, reverse, fuzzy + ref = self.info.call_refs.get(key) + if ref is not None: + code += [(OP.CALL_REF, ref)] + + code += [(OP.GROUP, int(not reverse), private_group, public_group)] + code += self.subpattern.compile(reverse, fuzzy) + code += [(OP.END, )] + + if ref is not None: + code += [(OP.END, )] + + return code + + def dump(self, indent, reverse): + group = self.group + if group < 0: + group = private_groups[group] + print("{}GROUP {}".format(INDENT * indent, group)) + self.subpattern.dump(indent + 1, reverse) + + def __eq__(self, other): + return (type(self) is type(other) and (self.group, self.subpattern) == + (other.group, other.subpattern)) + + def max_width(self): + return self.subpattern.max_width() + + def get_required_string(self, reverse): + return self.subpattern.get_required_string(reverse) + + def __del__(self): + self.info = None + +class Keep(ZeroWidthBase): + _opcode = OP.KEEP + _op_name = "KEEP" + +class LazyRepeat(GreedyRepeat): + _opcode = OP.LAZY_REPEAT + _op_name = "LAZY_REPEAT" + +class LookAround(RegexBase): + _dir_text = {False: "AHEAD", True: "BEHIND"} + + def __init__(self, behind, positive, subpattern): + RegexBase.__init__(self) + self.behind = bool(behind) + self.positive = bool(positive) + self.subpattern = subpattern + + def fix_groups(self, pattern, reverse, fuzzy): + self.subpattern.fix_groups(pattern, self.behind, fuzzy) + + def optimise(self, info, reverse): + subpattern = self.subpattern.optimise(info, self.behind) + if self.positive and subpattern.is_empty(): + return subpattern + + return LookAround(self.behind, self.positive, subpattern) + + def pack_characters(self, info): + self.subpattern = self.subpattern.pack_characters(info) + return self + + def remove_captures(self): + return self.subpattern.remove_captures() + + def is_atomic(self): + return self.subpattern.is_atomic() + + def can_be_affix(self): + return self.subpattern.can_be_affix() + + def contains_group(self): + return self.subpattern.contains_group() + + def get_firstset(self, reverse): + if self.positive and self.behind == reverse: + return self.subpattern.get_firstset(reverse) + + return set([None]) + + def _compile(self, reverse, fuzzy): + flags = 0 + if self.positive: + flags |= POSITIVE_OP + if fuzzy: + flags |= FUZZY_OP + if reverse: + flags |= REVERSE_OP + + return ([(OP.LOOKAROUND, flags, int(not self.behind))] + + self.subpattern.compile(self.behind) + [(OP.END, )]) + + def dump(self, indent, reverse): + print("{}LOOK{} {}".format(INDENT * indent, + self._dir_text[self.behind], POS_TEXT[self.positive])) + self.subpattern.dump(indent + 1, self.behind) + + def is_empty(self): + return self.positive and self.subpattern.is_empty() + + def __eq__(self, other): + return type(self) is type(other) and (self.behind, self.positive, + self.subpattern) == (other.behind, other.positive, other.subpattern) + + def max_width(self): + return 0 + +class LookAroundConditional(RegexBase): + _dir_text = {False: "AHEAD", True: "BEHIND"} + + def __init__(self, behind, positive, subpattern, yes_item, no_item): + RegexBase.__init__(self) + self.behind = bool(behind) + self.positive = bool(positive) + self.subpattern = subpattern + self.yes_item = yes_item + self.no_item = no_item + + def fix_groups(self, pattern, reverse, fuzzy): + self.subpattern.fix_groups(pattern, reverse, fuzzy) + self.yes_item.fix_groups(pattern, reverse, fuzzy) + self.no_item.fix_groups(pattern, reverse, fuzzy) + + def optimise(self, info, reverse): + subpattern = self.subpattern.optimise(info, self.behind) + yes_item = self.yes_item.optimise(info, self.behind) + no_item = self.no_item.optimise(info, self.behind) + + return LookAroundConditional(self.behind, self.positive, subpattern, + yes_item, no_item) + + def pack_characters(self, info): + self.subpattern = self.subpattern.pack_characters(info) + self.yes_item = self.yes_item.pack_characters(info) + self.no_item = self.no_item.pack_characters(info) + return self + + def remove_captures(self): + self.subpattern = self.subpattern.remove_captures() + self.yes_item = self.yes_item.remove_captures() + self.no_item = self.no_item.remove_captures() + + def is_atomic(self): + return (self.subpattern.is_atomic() and self.yes_item.is_atomic() and + self.no_item.is_atomic()) + + def can_be_affix(self): + return (self.subpattern.can_be_affix() and self.yes_item.can_be_affix() + and self.no_item.can_be_affix()) + + def contains_group(self): + return (self.subpattern.contains_group() or + self.yes_item.contains_group() or self.no_item.contains_group()) + + def _compile(self, reverse, fuzzy): + code = [(OP.CONDITIONAL, int(self.positive), int(not self.behind))] + code.extend(self.subpattern.compile(self.behind, fuzzy)) + code.append((OP.NEXT, )) + code.extend(self.yes_item.compile(reverse, fuzzy)) + add_code = self.no_item.compile(reverse, fuzzy) + if add_code: + code.append((OP.NEXT, )) + code.extend(add_code) + + code.append((OP.END, )) + + return code + + def dump(self, indent, reverse): + print("{}CONDITIONAL {} {}".format(INDENT * indent, + self._dir_text[self.behind], POS_TEXT[self.positive])) + self.subpattern.dump(indent + 1, self.behind) + print("{}EITHER".format(INDENT * indent)) + self.yes_item.dump(indent + 1, reverse) + if not self.no_item.is_empty(): + print("{}OR".format(INDENT * indent)) + self.no_item.dump(indent + 1, reverse) + + def is_empty(self): + return (self.subpattern.is_empty() and self.yes_item.is_empty() or + self.no_item.is_empty()) + + def __eq__(self, other): + return type(self) is type(other) and (self.subpattern, self.yes_item, + self.no_item) == (other.subpattern, other.yes_item, other.no_item) + + def max_width(self): + return max(self.yes_item.max_width(), self.no_item.max_width()) + + def get_required_string(self, reverse): + return self.max_width(), None + +class PrecompiledCode(RegexBase): + def __init__(self, code): + self.code = code + + def _compile(self, reverse, fuzzy): + return [tuple(self.code)] + +class Property(RegexBase): + _opcode = {(NOCASE, False): OP.PROPERTY, (IGNORECASE, False): + OP.PROPERTY_IGN, (FULLCASE, False): OP.PROPERTY, (FULLIGNORECASE, False): + OP.PROPERTY_IGN, (NOCASE, True): OP.PROPERTY_REV, (IGNORECASE, True): + OP.PROPERTY_IGN_REV, (FULLCASE, True): OP.PROPERTY_REV, (FULLIGNORECASE, + True): OP.PROPERTY_IGN_REV} + + def __init__(self, value, positive=True, case_flags=NOCASE, + zerowidth=False): + RegexBase.__init__(self) + self.value = value + self.positive = bool(positive) + self.case_flags = CASE_FLAGS_COMBINATIONS[case_flags] + self.zerowidth = bool(zerowidth) + + self._key = (self.__class__, self.value, self.positive, + self.case_flags, self.zerowidth) + + def rebuild(self, positive, case_flags, zerowidth): + return Property(self.value, positive, case_flags, zerowidth) + + def optimise(self, info, reverse, in_set=False): + return self + + def get_firstset(self, reverse): + return set([self]) + + def has_simple_start(self): + return True + + def _compile(self, reverse, fuzzy): + flags = 0 + if self.positive: + flags |= POSITIVE_OP + if self.zerowidth: + flags |= ZEROWIDTH_OP + if fuzzy: + flags |= FUZZY_OP + return [(self._opcode[self.case_flags, reverse], flags, self.value)] + + def dump(self, indent, reverse): + prop = PROPERTY_NAMES[self.value >> 16] + name, value = prop[0], prop[1][self.value & 0xFFFF] + print("{}PROPERTY {} {}:{}{}".format(INDENT * indent, + POS_TEXT[self.positive], name, value, CASE_TEXT[self.case_flags])) + + def matches(self, ch): + return _regex.has_property_value(self.value, ch) == self.positive + + def max_width(self): + return 1 + +class Prune(ZeroWidthBase): + _op_name = "PRUNE" + + def _compile(self, reverse, fuzzy): + return [(OP.PRUNE, )] + +class Range(RegexBase): + _opcode = {(NOCASE, False): OP.RANGE, (IGNORECASE, False): OP.RANGE_IGN, + (FULLCASE, False): OP.RANGE, (FULLIGNORECASE, False): OP.RANGE_IGN, + (NOCASE, True): OP.RANGE_REV, (IGNORECASE, True): OP.RANGE_IGN_REV, + (FULLCASE, True): OP.RANGE_REV, (FULLIGNORECASE, True): OP.RANGE_IGN_REV} + _op_name = "RANGE" + + def __init__(self, lower, upper, positive=True, case_flags=NOCASE, + zerowidth=False): + RegexBase.__init__(self) + self.lower = lower + self.upper = upper + self.positive = bool(positive) + self.case_flags = CASE_FLAGS_COMBINATIONS[case_flags] + self.zerowidth = bool(zerowidth) + + self._key = (self.__class__, self.lower, self.upper, self.positive, + self.case_flags, self.zerowidth) + + def rebuild(self, positive, case_flags, zerowidth): + return Range(self.lower, self.upper, positive, case_flags, zerowidth) + + def optimise(self, info, reverse, in_set=False): + # Is the range case-sensitive? + if not self.positive or not (self.case_flags & IGNORECASE) or in_set: + return self + + # Is full case-folding possible? + if (not (info.flags & UNICODE) or (self.case_flags & FULLIGNORECASE) != + FULLIGNORECASE): + return self + + # Get the characters which expand to multiple codepoints on folding. + expanding_chars = _regex.get_expand_on_folding() + + # Get the folded characters in the range. + items = [] + for ch in expanding_chars: + if self.lower <= ord(ch) <= self.upper: + folded = _regex.fold_case(FULL_CASE_FOLDING, ch) + items.append(String([ord(c) for c in folded], + case_flags=self.case_flags)) + + if not items: + # We can fall back to simple case-folding. + return self + + if len(items) < self.upper - self.lower + 1: + # Not all the characters are covered by the full case-folding. + items.insert(0, self) + + return Branch(items) + + def _compile(self, reverse, fuzzy): + flags = 0 + if self.positive: + flags |= POSITIVE_OP + if self.zerowidth: + flags |= ZEROWIDTH_OP + if fuzzy: + flags |= FUZZY_OP + return [(self._opcode[self.case_flags, reverse], flags, self.lower, + self.upper)] + + def dump(self, indent, reverse): + display_lower = ascii(chr(self.lower)).lstrip("bu") + display_upper = ascii(chr(self.upper)).lstrip("bu") + print("{}RANGE {} {} {}{}".format(INDENT * indent, + POS_TEXT[self.positive], display_lower, display_upper, + CASE_TEXT[self.case_flags])) + + def matches(self, ch): + return (self.lower <= ch <= self.upper) == self.positive + + def max_width(self): + return 1 + +class RefGroup(RegexBase): + _opcode = {(NOCASE, False): OP.REF_GROUP, (IGNORECASE, False): + OP.REF_GROUP_IGN, (FULLCASE, False): OP.REF_GROUP, (FULLIGNORECASE, + False): OP.REF_GROUP_FLD, (NOCASE, True): OP.REF_GROUP_REV, (IGNORECASE, + True): OP.REF_GROUP_IGN_REV, (FULLCASE, True): OP.REF_GROUP_REV, + (FULLIGNORECASE, True): OP.REF_GROUP_FLD_REV} + + def __init__(self, info, group, position, case_flags=NOCASE): + RegexBase.__init__(self) + self.info = info + self.group = group + self.position = position + self.case_flags = CASE_FLAGS_COMBINATIONS[case_flags] + + self._key = self.__class__, self.group, self.case_flags + + def fix_groups(self, pattern, reverse, fuzzy): + try: + self.group = int(self.group) + except ValueError: + try: + self.group = self.info.group_index[self.group] + except KeyError: + raise error("unknown group", pattern, self.position) + + if not 1 <= self.group <= self.info.group_count: + raise error("invalid group reference", pattern, self.position) + + self._key = self.__class__, self.group, self.case_flags + + def remove_captures(self): + raise error("group reference not allowed", pattern, self.position) + + def _compile(self, reverse, fuzzy): + flags = 0 + if fuzzy: + flags |= FUZZY_OP + return [(self._opcode[self.case_flags, reverse], flags, self.group)] + + def dump(self, indent, reverse): + print("{}REF_GROUP {}{}".format(INDENT * indent, self.group, + CASE_TEXT[self.case_flags])) + + def max_width(self): + return UNLIMITED + + def __del__(self): + self.info = None + +class SearchAnchor(ZeroWidthBase): + _opcode = OP.SEARCH_ANCHOR + _op_name = "SEARCH_ANCHOR" + +class Sequence(RegexBase): + def __init__(self, items=None): + RegexBase.__init__(self) + if items is None: + items = [] + + self.items = items + + def fix_groups(self, pattern, reverse, fuzzy): + for s in self.items: + s.fix_groups(pattern, reverse, fuzzy) + + def optimise(self, info, reverse): + # Flatten the sequences. + items = [] + for s in self.items: + s = s.optimise(info, reverse) + if isinstance(s, Sequence): + items.extend(s.items) + else: + items.append(s) + + return make_sequence(items) + + def pack_characters(self, info): + "Packs sequences of characters into strings." + items = [] + characters = [] + case_flags = NOCASE + for s in self.items: + if type(s) is Character and s.positive and not s.zerowidth: + if s.case_flags != case_flags: + # Different case sensitivity, so flush, unless neither the + # previous nor the new character are cased. + if s.case_flags or is_cased_i(info, s.value): + Sequence._flush_characters(info, characters, + case_flags, items) + + case_flags = s.case_flags + + characters.append(s.value) + elif type(s) is String or type(s) is Literal: + if s.case_flags != case_flags: + # Different case sensitivity, so flush, unless the neither + # the previous nor the new string are cased. + if s.case_flags or any(is_cased_i(info, c) for c in + characters): + Sequence._flush_characters(info, characters, + case_flags, items) + + case_flags = s.case_flags + + characters.extend(s.characters) + else: + Sequence._flush_characters(info, characters, case_flags, items) + + items.append(s.pack_characters(info)) + + Sequence._flush_characters(info, characters, case_flags, items) + + return make_sequence(items) + + def remove_captures(self): + self.items = [s.remove_captures() for s in self.items] + return self + + def is_atomic(self): + return all(s.is_atomic() for s in self.items) + + def can_be_affix(self): + return False + + def contains_group(self): + return any(s.contains_group() for s in self.items) + + def get_firstset(self, reverse): + fs = set() + items = self.items + if reverse: + items.reverse() + for s in items: + fs |= s.get_firstset(reverse) + if None not in fs: + return fs + fs.discard(None) + + return fs | set([None]) + + def has_simple_start(self): + return bool(self.items) and self.items[0].has_simple_start() + + def _compile(self, reverse, fuzzy): + seq = self.items + if reverse: + seq = seq[::-1] + + code = [] + for s in seq: + code.extend(s.compile(reverse, fuzzy)) + + return code + + def dump(self, indent, reverse): + for s in self.items: + s.dump(indent, reverse) + + @staticmethod + def _flush_characters(info, characters, case_flags, items): + if not characters: + return + + # Disregard case_flags if all of the characters are case-less. + if case_flags & IGNORECASE: + if not any(is_cased_i(info, c) for c in characters): + case_flags = NOCASE + + if (case_flags & FULLIGNORECASE) == FULLIGNORECASE: + literals = Sequence._fix_full_casefold(characters) + + for item in literals: + chars = item.characters + + if len(chars) == 1: + items.append(Character(chars[0], case_flags=item.case_flags)) + else: + items.append(String(chars, case_flags=item.case_flags)) + else: + if len(characters) == 1: + items.append(Character(characters[0], case_flags=case_flags)) + else: + items.append(String(characters, case_flags=case_flags)) + + characters[:] = [] + + @staticmethod + def _fix_full_casefold(characters): + # Split a literal needing full case-folding into chunks that need it + # and chunks that can use simple case-folding, which is faster. + expanded = [_regex.fold_case(FULL_CASE_FOLDING, c) for c in + _regex.get_expand_on_folding()] + string = _regex.fold_case(FULL_CASE_FOLDING, ''.join(chr(c) + for c in characters)).lower() + chunks = [] + + for e in expanded: + found = string.find(e) + + while found >= 0: + chunks.append((found, found + len(e))) + found = string.find(e, found + 1) + + pos = 0 + literals = [] + + for start, end in Sequence._merge_chunks(chunks): + if pos < start: + literals.append(Literal(characters[pos : start], + case_flags=IGNORECASE)) + + literals.append(Literal(characters[start : end], + case_flags=FULLIGNORECASE)) + pos = end + + if pos < len(characters): + literals.append(Literal(characters[pos : ], case_flags=IGNORECASE)) + + return literals + + @staticmethod + def _merge_chunks(chunks): + if len(chunks) < 2: + return chunks + + chunks.sort() + + start, end = chunks[0] + new_chunks = [] + + for s, e in chunks[1 : ]: + if s <= end: + end = max(end, e) + else: + new_chunks.append((start, end)) + start, end = s, e + + new_chunks.append((start, end)) + + return new_chunks + + def is_empty(self): + return all(i.is_empty() for i in self.items) + + def __eq__(self, other): + return type(self) is type(other) and self.items == other.items + + def max_width(self): + return sum(s.max_width() for s in self.items) + + def get_required_string(self, reverse): + seq = self.items + if reverse: + seq = seq[::-1] + + offset = 0 + + for s in seq: + ofs, req = s.get_required_string(reverse) + offset += ofs + if req: + return offset, req + + return offset, None + +class SetBase(RegexBase): + def __init__(self, info, items, positive=True, case_flags=NOCASE, + zerowidth=False): + RegexBase.__init__(self) + self.info = info + self.items = tuple(items) + self.positive = bool(positive) + self.case_flags = CASE_FLAGS_COMBINATIONS[case_flags] + self.zerowidth = bool(zerowidth) + + self.char_width = 1 + + self._key = (self.__class__, self.items, self.positive, + self.case_flags, self.zerowidth) + + def rebuild(self, positive, case_flags, zerowidth): + return type(self)(self.info, self.items, positive, case_flags, + zerowidth).optimise(self.info, False) + + def get_firstset(self, reverse): + return set([self]) + + def has_simple_start(self): + return True + + def _compile(self, reverse, fuzzy): + flags = 0 + if self.positive: + flags |= POSITIVE_OP + if self.zerowidth: + flags |= ZEROWIDTH_OP + if fuzzy: + flags |= FUZZY_OP + code = [(self._opcode[self.case_flags, reverse], flags)] + for m in self.items: + code.extend(m.compile()) + + code.append((OP.END, )) + + return code + + def dump(self, indent, reverse): + print("{}{} {}{}".format(INDENT * indent, self._op_name, + POS_TEXT[self.positive], CASE_TEXT[self.case_flags])) + for i in self.items: + i.dump(indent + 1, reverse) + + def _handle_case_folding(self, info, in_set): + # Is the set case-sensitive? + if not self.positive or not (self.case_flags & IGNORECASE) or in_set: + return self + + # Is full case-folding possible? + if (not (self.info.flags & UNICODE) or (self.case_flags & + FULLIGNORECASE) != FULLIGNORECASE): + return self + + # Get the characters which expand to multiple codepoints on folding. + expanding_chars = _regex.get_expand_on_folding() + + # Get the folded characters in the set. + items = [] + seen = set() + for ch in expanding_chars: + if self.matches(ord(ch)): + folded = _regex.fold_case(FULL_CASE_FOLDING, ch) + if folded not in seen: + items.append(String([ord(c) for c in folded], + case_flags=self.case_flags)) + seen.add(folded) + + if not items: + # We can fall back to simple case-folding. + return self + + return Branch([self] + items) + + def max_width(self): + # Is the set case-sensitive? + if not self.positive or not (self.case_flags & IGNORECASE): + return 1 + + # Is full case-folding possible? + if (not (self.info.flags & UNICODE) or (self.case_flags & + FULLIGNORECASE) != FULLIGNORECASE): + return 1 + + # Get the characters which expand to multiple codepoints on folding. + expanding_chars = _regex.get_expand_on_folding() + + # Get the folded characters in the set. + seen = set() + for ch in expanding_chars: + if self.matches(ord(ch)): + folded = _regex.fold_case(FULL_CASE_FOLDING, ch) + seen.add(folded) + + if not seen: + return 1 + + return max(len(folded) for folded in seen) + + def __del__(self): + self.info = None + +class SetDiff(SetBase): + _opcode = {(NOCASE, False): OP.SET_DIFF, (IGNORECASE, False): + OP.SET_DIFF_IGN, (FULLCASE, False): OP.SET_DIFF, (FULLIGNORECASE, False): + OP.SET_DIFF_IGN, (NOCASE, True): OP.SET_DIFF_REV, (IGNORECASE, True): + OP.SET_DIFF_IGN_REV, (FULLCASE, True): OP.SET_DIFF_REV, (FULLIGNORECASE, + True): OP.SET_DIFF_IGN_REV} + _op_name = "SET_DIFF" + + def optimise(self, info, reverse, in_set=False): + items = self.items + if len(items) > 2: + items = [items[0], SetUnion(info, items[1 : ])] + + if len(items) == 1: + return items[0].with_flags(case_flags=self.case_flags, + zerowidth=self.zerowidth).optimise(info, reverse, in_set) + + self.items = tuple(m.optimise(info, reverse, in_set=True) for m in + items) + + return self._handle_case_folding(info, in_set) + + def matches(self, ch): + m = self.items[0].matches(ch) and not self.items[1].matches(ch) + return m == self.positive + +class SetInter(SetBase): + _opcode = {(NOCASE, False): OP.SET_INTER, (IGNORECASE, False): + OP.SET_INTER_IGN, (FULLCASE, False): OP.SET_INTER, (FULLIGNORECASE, + False): OP.SET_INTER_IGN, (NOCASE, True): OP.SET_INTER_REV, (IGNORECASE, + True): OP.SET_INTER_IGN_REV, (FULLCASE, True): OP.SET_INTER_REV, + (FULLIGNORECASE, True): OP.SET_INTER_IGN_REV} + _op_name = "SET_INTER" + + def optimise(self, info, reverse, in_set=False): + items = [] + for m in self.items: + m = m.optimise(info, reverse, in_set=True) + if isinstance(m, SetInter) and m.positive: + # Intersection in intersection. + items.extend(m.items) + else: + items.append(m) + + if len(items) == 1: + return items[0].with_flags(case_flags=self.case_flags, + zerowidth=self.zerowidth).optimise(info, reverse, in_set) + + self.items = tuple(items) + + return self._handle_case_folding(info, in_set) + + def matches(self, ch): + m = all(i.matches(ch) for i in self.items) + return m == self.positive + +class SetSymDiff(SetBase): + _opcode = {(NOCASE, False): OP.SET_SYM_DIFF, (IGNORECASE, False): + OP.SET_SYM_DIFF_IGN, (FULLCASE, False): OP.SET_SYM_DIFF, (FULLIGNORECASE, + False): OP.SET_SYM_DIFF_IGN, (NOCASE, True): OP.SET_SYM_DIFF_REV, + (IGNORECASE, True): OP.SET_SYM_DIFF_IGN_REV, (FULLCASE, True): + OP.SET_SYM_DIFF_REV, (FULLIGNORECASE, True): OP.SET_SYM_DIFF_IGN_REV} + _op_name = "SET_SYM_DIFF" + + def optimise(self, info, reverse, in_set=False): + items = [] + for m in self.items: + m = m.optimise(info, reverse, in_set=True) + if isinstance(m, SetSymDiff) and m.positive: + # Symmetric difference in symmetric difference. + items.extend(m.items) + else: + items.append(m) + + if len(items) == 1: + return items[0].with_flags(case_flags=self.case_flags, + zerowidth=self.zerowidth).optimise(info, reverse, in_set) + + self.items = tuple(items) + + return self._handle_case_folding(info, in_set) + + def matches(self, ch): + m = False + for i in self.items: + m = m != i.matches(ch) + + return m == self.positive + +class SetUnion(SetBase): + _opcode = {(NOCASE, False): OP.SET_UNION, (IGNORECASE, False): + OP.SET_UNION_IGN, (FULLCASE, False): OP.SET_UNION, (FULLIGNORECASE, + False): OP.SET_UNION_IGN, (NOCASE, True): OP.SET_UNION_REV, (IGNORECASE, + True): OP.SET_UNION_IGN_REV, (FULLCASE, True): OP.SET_UNION_REV, + (FULLIGNORECASE, True): OP.SET_UNION_IGN_REV} + _op_name = "SET_UNION" + + def optimise(self, info, reverse, in_set=False): + items = [] + for m in self.items: + m = m.optimise(info, reverse, in_set=True) + if isinstance(m, SetUnion) and m.positive: + # Union in union. + items.extend(m.items) + else: + items.append(m) + + if len(items) == 1: + i = items[0] + return i.with_flags(positive=i.positive == self.positive, + case_flags=self.case_flags, + zerowidth=self.zerowidth).optimise(info, reverse, in_set) + + self.items = tuple(items) + + return self._handle_case_folding(info, in_set) + + def _compile(self, reverse, fuzzy): + flags = 0 + if self.positive: + flags |= POSITIVE_OP + if self.zerowidth: + flags |= ZEROWIDTH_OP + if fuzzy: + flags |= FUZZY_OP + + characters, others = defaultdict(list), [] + for m in self.items: + if isinstance(m, Character): + characters[m.positive].append(m.value) + else: + others.append(m) + + code = [(self._opcode[self.case_flags, reverse], flags)] + + for positive, values in characters.items(): + flags = 0 + if positive: + flags |= POSITIVE_OP + if len(values) == 1: + code.append((OP.CHARACTER, flags, values[0])) + else: + code.append((OP.STRING, flags, len(values)) + tuple(values)) + + for m in others: + code.extend(m.compile()) + + code.append((OP.END, )) + + return code + + def matches(self, ch): + m = any(i.matches(ch) for i in self.items) + return m == self.positive + +class Skip(ZeroWidthBase): + _op_name = "SKIP" + _opcode = OP.SKIP + +class StartOfLine(ZeroWidthBase): + _opcode = OP.START_OF_LINE + _op_name = "START_OF_LINE" + +class StartOfLineU(StartOfLine): + _opcode = OP.START_OF_LINE_U + _op_name = "START_OF_LINE_U" + +class StartOfString(ZeroWidthBase): + _opcode = OP.START_OF_STRING + _op_name = "START_OF_STRING" + +class StartOfWord(ZeroWidthBase): + _opcode = OP.START_OF_WORD + _op_name = "START_OF_WORD" + +class String(RegexBase): + _opcode = {(NOCASE, False): OP.STRING, (IGNORECASE, False): OP.STRING_IGN, + (FULLCASE, False): OP.STRING, (FULLIGNORECASE, False): OP.STRING_FLD, + (NOCASE, True): OP.STRING_REV, (IGNORECASE, True): OP.STRING_IGN_REV, + (FULLCASE, True): OP.STRING_REV, (FULLIGNORECASE, True): + OP.STRING_FLD_REV} + + def __init__(self, characters, case_flags=NOCASE): + self.characters = tuple(characters) + self.case_flags = CASE_FLAGS_COMBINATIONS[case_flags] + + if (self.case_flags & FULLIGNORECASE) == FULLIGNORECASE: + folded_characters = [] + for char in self.characters: + folded = _regex.fold_case(FULL_CASE_FOLDING, chr(char)) + folded_characters.extend(ord(c) for c in folded) + else: + folded_characters = self.characters + + self.folded_characters = tuple(folded_characters) + self.required = False + + self._key = self.__class__, self.characters, self.case_flags + + def get_firstset(self, reverse): + if reverse: + pos = -1 + else: + pos = 0 + return set([Character(self.characters[pos], + case_flags=self.case_flags)]) + + def has_simple_start(self): + return True + + def _compile(self, reverse, fuzzy): + flags = 0 + if fuzzy: + flags |= FUZZY_OP + if self.required: + flags |= REQUIRED_OP + return [(self._opcode[self.case_flags, reverse], flags, + len(self.folded_characters)) + self.folded_characters] + + def dump(self, indent, reverse): + display = ascii("".join(chr(c) for c in self.characters)).lstrip("bu") + print("{}STRING {}{}".format(INDENT * indent, display, + CASE_TEXT[self.case_flags])) + + def max_width(self): + return len(self.folded_characters) + + def get_required_string(self, reverse): + return 0, self + +class Literal(String): + def dump(self, indent, reverse): + literal = ''.join(chr(c) for c in self.characters) + display = ascii(literal).lstrip("bu") + print("{}LITERAL MATCH {}{}".format(INDENT * indent, display, + CASE_TEXT[self.case_flags])) + +class StringSet(Branch): + def __init__(self, info, name, case_flags=NOCASE): + self.info = info + self.name = name + self.case_flags = CASE_FLAGS_COMBINATIONS[case_flags] + + self._key = self.__class__, self.name, self.case_flags + + self.set_key = (name, self.case_flags) + if self.set_key not in info.named_lists_used: + info.named_lists_used[self.set_key] = len(info.named_lists_used) + + index = self.info.named_lists_used[self.set_key] + items = self.info.kwargs[self.name] + + case_flags = self.case_flags + + encoding = self.info.flags & _ALL_ENCODINGS + fold_flags = encoding | case_flags + + choices = [] + + for string in items: + if isinstance(string, str): + string = [ord(c) for c in string] + + choices.append([Character(c, case_flags=case_flags) for c in + string]) + + # Sort from longest to shortest. + choices.sort(key=len, reverse=True) + + self.branches = [Sequence(choice) for choice in choices] + + def dump(self, indent, reverse): + print("{}STRING_SET {}{}".format(INDENT * indent, self.name, + CASE_TEXT[self.case_flags])) + + def __del__(self): + self.info = None + +class Source: + "Scanner for the regular expression source string." + def __init__(self, string): + if isinstance(string, str): + self.string = string + self.char_type = chr + else: + self.string = string.decode("latin-1") + self.char_type = lambda c: bytes([c]) + + self.pos = 0 + self.ignore_space = False + self.sep = string[ : 0] + + def get(self, override_ignore=False): + string = self.string + pos = self.pos + + try: + if self.ignore_space and not override_ignore: + while True: + if string[pos].isspace(): + # Skip over the whitespace. + pos += 1 + elif string[pos] == "#": + # Skip over the comment to the end of the line. + pos = string.index("\n", pos) + else: + break + + ch = string[pos] + self.pos = pos + 1 + return ch + except IndexError: + # We've reached the end of the string. + self.pos = pos + return string[ : 0] + except ValueError: + # The comment extended to the end of the string. + self.pos = len(string) + return string[ : 0] + + def get_many(self, count=1): + string = self.string + pos = self.pos + + try: + if self.ignore_space: + substring = [] + + while len(substring) < count: + while True: + if string[pos].isspace(): + # Skip over the whitespace. + pos += 1 + elif string[pos] == "#": + # Skip over the comment to the end of the line. + pos = string.index("\n", pos) + else: + break + + substring.append(string[pos]) + pos += 1 + + substring = "".join(substring) + else: + substring = string[pos : pos + count] + pos += len(substring) + + self.pos = pos + return substring + except IndexError: + # We've reached the end of the string. + self.pos = len(string) + return "".join(substring) + except ValueError: + # The comment extended to the end of the string. + self.pos = len(string) + return "".join(substring) + + def get_while(self, test_set, include=True, keep_spaces=False): + string = self.string + pos = self.pos + + if self.ignore_space and not keep_spaces: + try: + substring = [] + + while True: + if string[pos].isspace(): + # Skip over the whitespace. + pos += 1 + elif string[pos] == "#": + # Skip over the comment to the end of the line. + pos = string.index("\n", pos) + elif (string[pos] in test_set) == include: + substring.append(string[pos]) + pos += 1 + else: + break + + self.pos = pos + except IndexError: + # We've reached the end of the string. + self.pos = len(string) + except ValueError: + # The comment extended to the end of the string. + self.pos = len(string) + + return "".join(substring) + else: + try: + while (string[pos] in test_set) == include: + pos += 1 + + substring = string[self.pos : pos] + + self.pos = pos + + return substring + except IndexError: + # We've reached the end of the string. + substring = string[self.pos : pos] + + self.pos = pos + + return substring + + def skip_while(self, test_set, include=True): + string = self.string + pos = self.pos + + try: + if self.ignore_space: + while True: + if string[pos].isspace(): + # Skip over the whitespace. + pos += 1 + elif string[pos] == "#": + # Skip over the comment to the end of the line. + pos = string.index("\n", pos) + elif (string[pos] in test_set) == include: + pos += 1 + else: + break + else: + while (string[pos] in test_set) == include: + pos += 1 + + self.pos = pos + except IndexError: + # We've reached the end of the string. + self.pos = len(string) + except ValueError: + # The comment extended to the end of the string. + self.pos = len(string) + + def match(self, substring): + string = self.string + pos = self.pos + + if self.ignore_space: + try: + for c in substring: + while True: + if string[pos].isspace(): + # Skip over the whitespace. + pos += 1 + elif string[pos] == "#": + # Skip over the comment to the end of the line. + pos = string.index("\n", pos) + else: + break + + if string[pos] != c: + return False + + pos += 1 + + self.pos = pos + + return True + except IndexError: + # We've reached the end of the string. + return False + except ValueError: + # The comment extended to the end of the string. + return False + else: + if not string.startswith(substring, pos): + return False + + self.pos = pos + len(substring) + + return True + + def expect(self, substring): + if not self.match(substring): + raise error("missing {}".format(substring), self.string, self.pos) + + def at_end(self): + string = self.string + pos = self.pos + + try: + if self.ignore_space: + while True: + if string[pos].isspace(): + pos += 1 + elif string[pos] == "#": + pos = string.index("\n", pos) + else: + break + + return pos >= len(string) + except IndexError: + # We've reached the end of the string. + return True + except ValueError: + # The comment extended to the end of the string. + return True + +class Info: + "Info about the regular expression." + + def __init__(self, flags=0, char_type=None, kwargs={}): + flags |= DEFAULT_FLAGS[(flags & _ALL_VERSIONS) or DEFAULT_VERSION] + self.flags = flags + self.global_flags = flags + self.inline_locale = False + + self.kwargs = kwargs + + self.group_count = 0 + self.group_index = {} + self.group_name = {} + self.char_type = char_type + self.named_lists_used = {} + self.open_groups = [] + self.open_group_count = {} + self.defined_groups = {} + self.group_calls = [] + self.private_groups = {} + + def open_group(self, name=None): + group = self.group_index.get(name) + if group is None: + while True: + self.group_count += 1 + if name is None or self.group_count not in self.group_name: + break + + group = self.group_count + if name: + self.group_index[name] = group + self.group_name[group] = name + + if group in self.open_groups: + # We have a nested named group. We'll assign it a private group + # number, initially negative until we can assign a proper + # (positive) number. + group_alias = -(len(self.private_groups) + 1) + self.private_groups[group_alias] = group + group = group_alias + + self.open_groups.append(group) + self.open_group_count[group] = self.open_group_count.get(group, 0) + 1 + + return group + + def close_group(self): + self.open_groups.pop() + + def is_open_group(self, name): + # In version 1, a group reference can refer to an open group. We'll + # just pretend the group isn't open. + version = (self.flags & _ALL_VERSIONS) or DEFAULT_VERSION + if version == VERSION1: + return False + + if name.isdigit(): + group = int(name) + else: + group = self.group_index.get(name) + + return group in self.open_groups + +def _check_group_features(info, parsed): + """Checks whether the reverse and fuzzy features of the group calls match + the groups which they call. + """ + call_refs = {} + additional_groups = [] + for call, reverse, fuzzy in info.group_calls: + # Look up the reference of this group call. + key = (call.group, reverse, fuzzy) + ref = call_refs.get(key) + if ref is None: + # This group doesn't have a reference yet, so look up its features. + if call.group == 0: + # Calling the pattern as a whole. + rev = bool(info.flags & REVERSE) + fuz = isinstance(parsed, Fuzzy) + if (rev, fuz) != (reverse, fuzzy): + # The pattern as a whole doesn't have the features we want, + # so we'll need to make a copy of it with the desired + # features. + additional_groups.append((CallRef(len(call_refs), parsed), + reverse, fuzzy)) + else: + # Calling a capture group. + def_info = info.defined_groups[call.group] + group = def_info[0] + if def_info[1 : ] != (reverse, fuzzy): + # The group doesn't have the features we want, so we'll + # need to make a copy of it with the desired features. + additional_groups.append((group, reverse, fuzzy)) + + ref = len(call_refs) + call_refs[key] = ref + + call.call_ref = ref + + info.call_refs = call_refs + info.additional_groups = additional_groups + +def _get_required_string(parsed, flags): + "Gets the required string and related info of a parsed pattern." + + req_offset, required = parsed.get_required_string(bool(flags & REVERSE)) + if required: + required.required = True + if req_offset >= UNLIMITED: + req_offset = -1 + + req_flags = required.case_flags + if not (flags & UNICODE): + req_flags &= ~UNICODE + + req_chars = required.folded_characters + else: + req_offset = 0 + req_chars = () + req_flags = 0 + + return req_offset, req_chars, req_flags + +class Scanner: + def __init__(self, lexicon, flags=0): + self.lexicon = lexicon + + # Combine phrases into a compound pattern. + patterns = [] + for phrase, action in lexicon: + # Parse the regular expression. + source = Source(phrase) + info = Info(flags, source.char_type) + source.ignore_space = bool(info.flags & VERBOSE) + parsed = _parse_pattern(source, info) + if not source.at_end(): + raise error("unbalanced parenthesis", source.string, + source.pos) + + # We want to forbid capture groups within each phrase. + patterns.append(parsed.remove_captures()) + + # Combine all the subpatterns into one pattern. + info = Info(flags) + patterns = [Group(info, g + 1, p) for g, p in enumerate(patterns)] + parsed = Branch(patterns) + + # Optimise the compound pattern. + reverse = bool(info.flags & REVERSE) + parsed = parsed.optimise(info, reverse) + parsed = parsed.pack_characters(info) + + # Get the required string. + req_offset, req_chars, req_flags = _get_required_string(parsed, + info.flags) + + # Check the features of the groups. + _check_group_features(info, parsed) + + # Complain if there are any group calls. They are not supported by the + # Scanner class. + if info.call_refs: + raise error("recursive regex not supported by Scanner", + source.string, source.pos) + + reverse = bool(info.flags & REVERSE) + + # Compile the compound pattern. The result is a list of tuples. + code = parsed.compile(reverse) + [(OP.SUCCESS, )] + + # Flatten the code into a list of ints. + code = _flatten_code(code) + + if not parsed.has_simple_start(): + # Get the first set, if possible. + try: + fs_code = _compile_firstset(info, parsed.get_firstset(reverse)) + fs_code = _flatten_code(fs_code) + code = fs_code + code + except _FirstSetError: + pass + + # Check the global flags for conflicts. + version = (info.flags & _ALL_VERSIONS) or DEFAULT_VERSION + if version not in (0, VERSION0, VERSION1): + raise ValueError("VERSION0 and VERSION1 flags are mutually incompatible") + + # Create the PatternObject. + # + # Local flags like IGNORECASE affect the code generation, but aren't + # needed by the PatternObject itself. Conversely, global flags like + # LOCALE _don't_ affect the code generation but _are_ needed by the + # PatternObject. + self.scanner = _regex.compile(None, (flags & GLOBAL_FLAGS) | version, + code, {}, {}, {}, [], req_offset, req_chars, req_flags, + len(patterns)) + + def scan(self, string): + result = [] + append = result.append + match = self.scanner.scanner(string).match + i = 0 + while True: + m = match() + if not m: + break + j = m.end() + if i == j: + break + action = self.lexicon[m.lastindex - 1][1] + if hasattr(action, '__call__'): + self.match = m + action = action(self, m.group()) + if action is not None: + append(action) + i = j + + return result, string[i : ] + +# Get the known properties dict. +PROPERTIES = _regex.get_properties() + +# Build the inverse of the properties dict. +PROPERTY_NAMES = {} +for prop_name, (prop_id, values) in PROPERTIES.items(): + name, prop_values = PROPERTY_NAMES.get(prop_id, ("", {})) + name = max(name, prop_name, key=len) + PROPERTY_NAMES[prop_id] = name, prop_values + + for val_name, val_id in values.items(): + prop_values[val_id] = max(prop_values.get(val_id, ""), val_name, + key=len) + +# Character escape sequences. +CHARACTER_ESCAPES = { + "a": "\a", + "b": "\b", + "f": "\f", + "n": "\n", + "r": "\r", + "t": "\t", + "v": "\v", +} + +# Predefined character set escape sequences. +CHARSET_ESCAPES = { + "d": lookup_property(None, "Digit", True), + "D": lookup_property(None, "Digit", False), + "h": lookup_property(None, "Blank", True), + "s": lookup_property(None, "Space", True), + "S": lookup_property(None, "Space", False), + "w": lookup_property(None, "Word", True), + "W": lookup_property(None, "Word", False), +} + +# Positional escape sequences. +POSITION_ESCAPES = { + "A": StartOfString(), + "b": Boundary(), + "B": Boundary(False), + "K": Keep(), + "m": StartOfWord(), + "M": EndOfWord(), + "Z": EndOfString(), +} + +# Positional escape sequences when WORD flag set. +WORD_POSITION_ESCAPES = dict(POSITION_ESCAPES) +WORD_POSITION_ESCAPES.update({ + "b": DefaultBoundary(), + "B": DefaultBoundary(False), + "m": DefaultStartOfWord(), + "M": DefaultEndOfWord(), +}) + +# Regex control verbs. +VERBS = { + "FAIL": Failure(), + "F": Failure(), + "PRUNE": Prune(), + "SKIP": Skip(), +} \ No newline at end of file diff --git a/opteryx/third_party/mrabarnett/regex/regex.py b/opteryx/third_party/mrabarnett/regex/regex.py new file mode 100644 index 000000000..c107e2b08 --- /dev/null +++ b/opteryx/third_party/mrabarnett/regex/regex.py @@ -0,0 +1,746 @@ +# +# Secret Labs' Regular Expression Engine +# +# Copyright (c) 1998-2001 by Secret Labs AB. All rights reserved. +# +# This version of the SRE library can be redistributed under CNRI's +# Python 1.6 license. For any other use, please contact Secret Labs +# AB (info@pythonware.com). +# +# Portions of this engine have been developed in cooperation with +# CNRI. Hewlett-Packard provided funding for 1.6 integration and +# other compatibility work. +# +# 2010-01-16 mrab Python front-end re-written and extended + +r"""Support for regular expressions (RE). + +This module provides regular expression matching operations similar to those +found in Perl. It supports both 8-bit and Unicode strings; both the pattern and +the strings being processed can contain null bytes and characters outside the +US ASCII range. + +Regular expressions can contain both special and ordinary characters. Most +ordinary characters, like "A", "a", or "0", are the simplest regular +expressions; they simply match themselves. You can concatenate ordinary +characters, so last matches the string 'last'. + +There are a few differences between the old (legacy) behaviour and the new +(enhanced) behaviour, which are indicated by VERSION0 or VERSION1. + +The special characters are: + "." Matches any character except a newline. + "^" Matches the start of the string. + "$" Matches the end of the string or just before the + newline at the end of the string. + "*" Matches 0 or more (greedy) repetitions of the preceding + RE. Greedy means that it will match as many repetitions + as possible. + "+" Matches 1 or more (greedy) repetitions of the preceding + RE. + "?" Matches 0 or 1 (greedy) of the preceding RE. + *?,+?,?? Non-greedy versions of the previous three special + characters. + *+,++,?+ Possessive versions of the previous three special + characters. + {m,n} Matches from m to n repetitions of the preceding RE. + {m,n}? Non-greedy version of the above. + {m,n}+ Possessive version of the above. + {...} Fuzzy matching constraints. + "\\" Either escapes special characters or signals a special + sequence. + [...] Indicates a set of characters. A "^" as the first + character indicates a complementing set. + "|" A|B, creates an RE that will match either A or B. + (...) Matches the RE inside the parentheses. The contents are + captured and can be retrieved or matched later in the + string. + (?flags-flags) VERSION1: Sets/clears the flags for the remainder of + the group or pattern; VERSION0: Sets the flags for the + entire pattern. + (?:...) Non-capturing version of regular parentheses. + (?>...) Atomic non-capturing version of regular parentheses. + (?flags-flags:...) Non-capturing version of regular parentheses with local + flags. + (?P...) The substring matched by the group is accessible by + name. + (?...) The substring matched by the group is accessible by + name. + (?P=name) Matches the text matched earlier by the group named + name. + (?#...) A comment; ignored. + (?=...) Matches if ... matches next, but doesn't consume the + string. + (?!...) Matches if ... doesn't match next. + (?<=...) Matches if preceded by .... + (? Matches the text matched by the group named name. + \G Matches the empty string, but only at the position where + the search started. + \h Matches horizontal whitespace. + \K Keeps only what follows for the entire match. + \L Named list. The list is provided as a keyword argument. + \m Matches the empty string, but only at the start of a word. + \M Matches the empty string, but only at the end of a word. + \n Matches the newline character. + \N{name} Matches the named character. + \p{name=value} Matches the character if its property has the specified + value. + \P{name=value} Matches the character if its property hasn't the specified + value. + \r Matches the carriage-return character. + \s Matches any whitespace character; equivalent to + [ \t\n\r\f\v]. + \S Matches any non-whitespace character; equivalent to [^\s]. + \t Matches the tab character. + \uXXXX Matches the Unicode codepoint with 4-digit hex code XXXX. + \UXXXXXXXX Matches the Unicode codepoint with 8-digit hex code + XXXXXXXX. + \v Matches the vertical tab character. + \w Matches any alphanumeric character; equivalent to + [a-zA-Z0-9_] when matching a bytestring or a Unicode string + with the ASCII flag, or the whole range of Unicode + alphanumeric characters (letters plus digits plus + underscore) when matching a Unicode string. With LOCALE, it + will match the set [0-9_] plus characters defined as + letters for the current locale. + \W Matches the complement of \w; equivalent to [^\w]. + \xXX Matches the character with 2-digit hex code XX. + \X Matches a grapheme. + \Z Matches only at the end of the string. + \\ Matches a literal backslash. + +This module exports the following functions: + match Match a regular expression pattern at the beginning of a string. + fullmatch Match a regular expression pattern against all of a string. + search Search a string for the presence of a pattern. + sub Substitute occurrences of a pattern found in a string using a + template string. + subf Substitute occurrences of a pattern found in a string using a + format string. + subn Same as sub, but also return the number of substitutions made. + subfn Same as subf, but also return the number of substitutions made. + split Split a string by the occurrences of a pattern. VERSION1: will + split at zero-width match; VERSION0: won't split at zero-width + match. + splititer Return an iterator yielding the parts of a split string. + findall Find all occurrences of a pattern in a string. + finditer Return an iterator yielding a match object for each match. + compile Compile a pattern into a Pattern object. + purge Clear the regular expression cache. + escape Backslash all non-alphanumerics or special characters in a + string. + +Most of the functions support a concurrent parameter: if True, the GIL will be +released during matching, allowing other Python threads to run concurrently. If +the string changes during matching, the behaviour is undefined. This parameter +is not needed when working on the builtin (immutable) string classes. + +Some of the functions in this module take flags as optional parameters. Most of +these flags can also be set within an RE: + A a ASCII Make \w, \W, \b, \B, \d, and \D match the + corresponding ASCII character categories. Default + when matching a bytestring. + B b BESTMATCH Find the best fuzzy match (default is first). + D DEBUG Print the parsed pattern. + E e ENHANCEMATCH Attempt to improve the fit after finding the first + fuzzy match. + F f FULLCASE Use full case-folding when performing + case-insensitive matching in Unicode. + I i IGNORECASE Perform case-insensitive matching. + L L LOCALE Make \w, \W, \b, \B, \d, and \D dependent on the + current locale. (One byte per character only.) + M m MULTILINE "^" matches the beginning of lines (after a newline) + as well as the string. "$" matches the end of lines + (before a newline) as well as the end of the string. + P p POSIX Perform POSIX-standard matching (leftmost longest). + R r REVERSE Searches backwards. + S s DOTALL "." matches any character at all, including the + newline. + U u UNICODE Make \w, \W, \b, \B, \d, and \D dependent on the + Unicode locale. Default when matching a Unicode + string. + V0 V0 VERSION0 Turn on the old legacy behaviour. + V1 V1 VERSION1 Turn on the new enhanced behaviour. This flag + includes the FULLCASE flag. + W w WORD Make \b and \B work with default Unicode word breaks + and make ".", "^" and "$" work with Unicode line + breaks. + X x VERBOSE Ignore whitespace and comments for nicer looking REs. + +This module also defines an exception 'error'. + +""" + +# Public symbols. +__all__ = ["cache_all", "compile", "DEFAULT_VERSION", "escape", "findall", + "finditer", "fullmatch", "match", "purge", "search", "split", "splititer", + "sub", "subf", "subfn", "subn", "template", "Scanner", "A", "ASCII", "B", + "BESTMATCH", "D", "DEBUG", "E", "ENHANCEMATCH", "S", "DOTALL", "F", + "FULLCASE", "I", "IGNORECASE", "L", "LOCALE", "M", "MULTILINE", "P", "POSIX", + "R", "REVERSE", "T", "TEMPLATE", "U", "UNICODE", "V0", "VERSION0", "V1", + "VERSION1", "X", "VERBOSE", "W", "WORD", "error", "Regex", "__version__", + "__doc__", "RegexFlag"] + +__version__ = "2.5.149" + +# -------------------------------------------------------------------- +# Public interface. + +def match(pattern, string, flags=0, pos=None, endpos=None, partial=False, + concurrent=None, timeout=None, ignore_unused=False, **kwargs): + """Try to apply the pattern at the start of the string, returning a match + object, or None if no match was found.""" + pat = _compile(pattern, flags, ignore_unused, kwargs, True) + return pat.match(string, pos, endpos, concurrent, partial, timeout) + +def fullmatch(pattern, string, flags=0, pos=None, endpos=None, partial=False, + concurrent=None, timeout=None, ignore_unused=False, **kwargs): + """Try to apply the pattern against all of the string, returning a match + object, or None if no match was found.""" + pat = _compile(pattern, flags, ignore_unused, kwargs, True) + return pat.fullmatch(string, pos, endpos, concurrent, partial, timeout) + +def search(pattern, string, flags=0, pos=None, endpos=None, partial=False, + concurrent=None, timeout=None, ignore_unused=False, **kwargs): + """Search through string looking for a match to the pattern, returning a + match object, or None if no match was found.""" + pat = _compile(pattern, flags, ignore_unused, kwargs, True) + return pat.search(string, pos, endpos, concurrent, partial, timeout) + +def sub(pattern, repl, string, count=0, flags=0, pos=None, endpos=None, + concurrent=None, timeout=None, ignore_unused=False, **kwargs): + """Return the string obtained by replacing the leftmost (or rightmost with a + reverse pattern) non-overlapping occurrences of the pattern in string by the + replacement repl. repl can be either a string or a callable; if a string, + backslash escapes in it are processed; if a callable, it's passed the match + object and must return a replacement string to be used.""" + pat = _compile(pattern, flags, ignore_unused, kwargs, True) + return pat.sub(repl, string, count, pos, endpos, concurrent, timeout) + +def subf(pattern, format, string, count=0, flags=0, pos=None, endpos=None, + concurrent=None, timeout=None, ignore_unused=False, **kwargs): + """Return the string obtained by replacing the leftmost (or rightmost with a + reverse pattern) non-overlapping occurrences of the pattern in string by the + replacement format. format can be either a string or a callable; if a string, + it's treated as a format string; if a callable, it's passed the match object + and must return a replacement string to be used.""" + pat = _compile(pattern, flags, ignore_unused, kwargs, True) + return pat.subf(format, string, count, pos, endpos, concurrent, timeout) + +def subn(pattern, repl, string, count=0, flags=0, pos=None, endpos=None, + concurrent=None, timeout=None, ignore_unused=False, **kwargs): + """Return a 2-tuple containing (new_string, number). new_string is the string + obtained by replacing the leftmost (or rightmost with a reverse pattern) + non-overlapping occurrences of the pattern in the source string by the + replacement repl. number is the number of substitutions that were made. repl + can be either a string or a callable; if a string, backslash escapes in it + are processed; if a callable, it's passed the match object and must return a + replacement string to be used.""" + pat = _compile(pattern, flags, ignore_unused, kwargs, True) + return pat.subn(repl, string, count, pos, endpos, concurrent, timeout) + +def subfn(pattern, format, string, count=0, flags=0, pos=None, endpos=None, + concurrent=None, timeout=None, ignore_unused=False, **kwargs): + """Return a 2-tuple containing (new_string, number). new_string is the string + obtained by replacing the leftmost (or rightmost with a reverse pattern) + non-overlapping occurrences of the pattern in the source string by the + replacement format. number is the number of substitutions that were made. format + can be either a string or a callable; if a string, it's treated as a format + string; if a callable, it's passed the match object and must return a + replacement string to be used.""" + pat = _compile(pattern, flags, ignore_unused, kwargs, True) + return pat.subfn(format, string, count, pos, endpos, concurrent, timeout) + +def split(pattern, string, maxsplit=0, flags=0, concurrent=None, timeout=None, + ignore_unused=False, **kwargs): + """Split the source string by the occurrences of the pattern, returning a + list containing the resulting substrings. If capturing parentheses are used + in pattern, then the text of all groups in the pattern are also returned as + part of the resulting list. If maxsplit is nonzero, at most maxsplit splits + occur, and the remainder of the string is returned as the final element of + the list.""" + pat = _compile(pattern, flags, ignore_unused, kwargs, True) + return pat.split(string, maxsplit, concurrent, timeout) + +def splititer(pattern, string, maxsplit=0, flags=0, concurrent=None, + timeout=None, ignore_unused=False, **kwargs): + "Return an iterator yielding the parts of a split string." + pat = _compile(pattern, flags, ignore_unused, kwargs, True) + return pat.splititer(string, maxsplit, concurrent, timeout) + +def findall(pattern, string, flags=0, pos=None, endpos=None, overlapped=False, + concurrent=None, timeout=None, ignore_unused=False, **kwargs): + """Return a list of all matches in the string. The matches may be overlapped + if overlapped is True. If one or more groups are present in the pattern, + return a list of groups; this will be a list of tuples if the pattern has + more than one group. Empty matches are included in the result.""" + pat = _compile(pattern, flags, ignore_unused, kwargs, True) + return pat.findall(string, pos, endpos, overlapped, concurrent, timeout) + +def finditer(pattern, string, flags=0, pos=None, endpos=None, overlapped=False, + partial=False, concurrent=None, timeout=None, ignore_unused=False, **kwargs): + """Return an iterator over all matches in the string. The matches may be + overlapped if overlapped is True. For each match, the iterator returns a + match object. Empty matches are included in the result.""" + pat = _compile(pattern, flags, ignore_unused, kwargs, True) + return pat.finditer(string, pos, endpos, overlapped, concurrent, partial, + timeout) + +def compile(pattern, flags=0, ignore_unused=False, cache_pattern=None, **kwargs): + "Compile a regular expression pattern, returning a pattern object." + if cache_pattern is None: + cache_pattern = _cache_all + return _compile(pattern, flags, ignore_unused, kwargs, cache_pattern) + +def purge(): + "Clear the regular expression cache" + _cache.clear() + _locale_sensitive.clear() + +# Whether to cache all patterns. +_cache_all = True + +def cache_all(value=True): + """Sets whether to cache all patterns, even those are compiled explicitly. + Passing None has no effect, but returns the current setting.""" + global _cache_all + + if value is None: + return _cache_all + + _cache_all = value + +def template(pattern, flags=0): + "Compile a template pattern, returning a pattern object." + return _compile(pattern, flags | TEMPLATE, False, {}, False) + +def escape(pattern, special_only=True, literal_spaces=False): + """Escape a string for use as a literal in a pattern. If special_only is + True, escape only special characters, else escape all non-alphanumeric + characters. If literal_spaces is True, don't escape spaces.""" + # Convert it to Unicode. + if isinstance(pattern, bytes): + p = pattern.decode("latin-1") + else: + p = pattern + + s = [] + if special_only: + for c in p: + if c == " " and literal_spaces: + s.append(c) + elif c in _METACHARS or c.isspace(): + s.append("\\") + s.append(c) + else: + s.append(c) + else: + for c in p: + if c == " " and literal_spaces: + s.append(c) + elif c in _ALNUM: + s.append(c) + else: + s.append("\\") + s.append(c) + + r = "".join(s) + # Convert it back to bytes if necessary. + if isinstance(pattern, bytes): + r = r.encode("latin-1") + + return r + +# -------------------------------------------------------------------- +# Internals. + +import regex._regex_core as _regex_core +import regex._regex as _regex +from threading import RLock as _RLock +from locale import getpreferredencoding as _getpreferredencoding +from regex._regex_core import * +from regex._regex_core import (_ALL_VERSIONS, _ALL_ENCODINGS, _FirstSetError, + _UnscopedFlagSet, _check_group_features, _compile_firstset, + _compile_replacement, _flatten_code, _fold_case, _get_required_string, + _parse_pattern, _shrink_cache) +from regex._regex_core import (ALNUM as _ALNUM, Info as _Info, OP as _OP, Source + as _Source, Fuzzy as _Fuzzy) + +# Version 0 is the old behaviour, compatible with the original 're' module. +# Version 1 is the new behaviour, which differs slightly. + +DEFAULT_VERSION = VERSION0 + +_METACHARS = frozenset("()[]{}?*+|^$\\.-#&~") + +_regex_core.DEFAULT_VERSION = DEFAULT_VERSION + +# Caches for the patterns and replacements. +_cache = {} +_cache_lock = _RLock() +_named_args = {} +_replacement_cache = {} +_locale_sensitive = {} + +# Maximum size of the cache. +_MAXCACHE = 500 +_MAXREPCACHE = 500 + +def _compile(pattern, flags, ignore_unused, kwargs, cache_it): + "Compiles a regular expression to a PatternObject." + + global DEFAULT_VERSION + try: + from regex import DEFAULT_VERSION + except ImportError: + pass + + # We won't bother to cache the pattern if we're debugging. + if (flags & DEBUG) != 0: + cache_it = False + + # What locale is this pattern using? + locale_key = (type(pattern), pattern) + if _locale_sensitive.get(locale_key, True) or (flags & LOCALE) != 0: + # This pattern is, or might be, locale-sensitive. + pattern_locale = _getpreferredencoding() + else: + # This pattern is definitely not locale-sensitive. + pattern_locale = None + + def complain_unused_args(): + if ignore_unused: + return + + # Complain about any unused keyword arguments, possibly resulting from a typo. + unused_kwargs = set(kwargs) - {k for k, v in args_needed} + if unused_kwargs: + any_one = next(iter(unused_kwargs)) + raise ValueError('unused keyword argument {!a}'.format(any_one)) + + if cache_it: + try: + # Do we know what keyword arguments are needed? + args_key = pattern, type(pattern), flags + args_needed = _named_args[args_key] + + # Are we being provided with its required keyword arguments? + args_supplied = set() + if args_needed: + for k, v in args_needed: + try: + args_supplied.add((k, frozenset(kwargs[k]))) + except KeyError: + raise error("missing named list: {!r}".format(k)) + + complain_unused_args() + + args_supplied = frozenset(args_supplied) + + # Have we already seen this regular expression and named list? + pattern_key = (pattern, type(pattern), flags, args_supplied, + DEFAULT_VERSION, pattern_locale) + return _cache[pattern_key] + except KeyError: + # It's a new pattern, or new named list for a known pattern. + pass + + # Guess the encoding from the class of the pattern string. + if isinstance(pattern, str): + guess_encoding = UNICODE + elif isinstance(pattern, bytes): + guess_encoding = ASCII + elif isinstance(pattern, Pattern): + if flags: + raise ValueError("cannot process flags argument with a compiled pattern") + + return pattern + else: + raise TypeError("first argument must be a string or compiled pattern") + + # Set the default version in the core code in case it has been changed. + _regex_core.DEFAULT_VERSION = DEFAULT_VERSION + + global_flags = flags + + while True: + caught_exception = None + try: + source = _Source(pattern) + info = _Info(global_flags, source.char_type, kwargs) + info.guess_encoding = guess_encoding + source.ignore_space = bool(info.flags & VERBOSE) + parsed = _parse_pattern(source, info) + break + except _UnscopedFlagSet: + # Remember the global flags for the next attempt. + global_flags = info.global_flags + except error as e: + caught_exception = e + + if caught_exception: + raise error(caught_exception.msg, caught_exception.pattern, + caught_exception.pos) + + if not source.at_end(): + raise error("unbalanced parenthesis", pattern, source.pos) + + # Check the global flags for conflicts. + version = (info.flags & _ALL_VERSIONS) or DEFAULT_VERSION + if version not in (0, VERSION0, VERSION1): + raise ValueError("VERSION0 and VERSION1 flags are mutually incompatible") + + if (info.flags & _ALL_ENCODINGS) not in (0, ASCII, LOCALE, UNICODE): + raise ValueError("ASCII, LOCALE and UNICODE flags are mutually incompatible") + + if isinstance(pattern, bytes) and (info.flags & UNICODE): + raise ValueError("cannot use UNICODE flag with a bytes pattern") + + if not (info.flags & _ALL_ENCODINGS): + if isinstance(pattern, str): + info.flags |= UNICODE + else: + info.flags |= ASCII + + reverse = bool(info.flags & REVERSE) + fuzzy = isinstance(parsed, _Fuzzy) + + # Remember whether this pattern as an inline locale flag. + _locale_sensitive[locale_key] = info.inline_locale + + # Fix the group references. + caught_exception = None + try: + parsed.fix_groups(pattern, reverse, False) + except error as e: + caught_exception = e + + if caught_exception: + raise error(caught_exception.msg, caught_exception.pattern, + caught_exception.pos) + + # Should we print the parsed pattern? + if flags & DEBUG: + parsed.dump(indent=0, reverse=reverse) + + # Optimise the parsed pattern. + parsed = parsed.optimise(info, reverse) + parsed = parsed.pack_characters(info) + + # Get the required string. + req_offset, req_chars, req_flags = _get_required_string(parsed, info.flags) + + # Build the named lists. + named_lists = {} + named_list_indexes = [None] * len(info.named_lists_used) + args_needed = set() + for key, index in info.named_lists_used.items(): + name, case_flags = key + values = frozenset(kwargs[name]) + if case_flags: + items = frozenset(_fold_case(info, v) for v in values) + else: + items = values + named_lists[name] = values + named_list_indexes[index] = items + args_needed.add((name, values)) + + complain_unused_args() + + # Check the features of the groups. + _check_group_features(info, parsed) + + # Compile the parsed pattern. The result is a list of tuples. + code = parsed.compile(reverse) + + # Is there a group call to the pattern as a whole? + key = (0, reverse, fuzzy) + ref = info.call_refs.get(key) + if ref is not None: + code = [(_OP.CALL_REF, ref)] + code + [(_OP.END, )] + + # Add the final 'success' opcode. + code += [(_OP.SUCCESS, )] + + # Compile the additional copies of the groups that we need. + for group, rev, fuz in info.additional_groups: + code += group.compile(rev, fuz) + + # Flatten the code into a list of ints. + code = _flatten_code(code) + + if not parsed.has_simple_start(): + # Get the first set, if possible. + try: + fs_code = _compile_firstset(info, parsed.get_firstset(reverse)) + fs_code = _flatten_code(fs_code) + code = fs_code + code + except _FirstSetError: + pass + + # The named capture groups. + index_group = dict((v, n) for n, v in info.group_index.items()) + + # Create the PatternObject. + # + # Local flags like IGNORECASE affect the code generation, but aren't needed + # by the PatternObject itself. Conversely, global flags like LOCALE _don't_ + # affect the code generation but _are_ needed by the PatternObject. + compiled_pattern = _regex.compile(pattern, info.flags | version, code, + info.group_index, index_group, named_lists, named_list_indexes, + req_offset, req_chars, req_flags, info.group_count) + + # Do we need to reduce the size of the cache? + if len(_cache) >= _MAXCACHE: + with _cache_lock: + _shrink_cache(_cache, _named_args, _locale_sensitive, _MAXCACHE) + + if cache_it: + if (info.flags & LOCALE) == 0: + pattern_locale = None + + args_needed = frozenset(args_needed) + + # Store this regular expression and named list. + pattern_key = (pattern, type(pattern), flags, args_needed, + DEFAULT_VERSION, pattern_locale) + _cache[pattern_key] = compiled_pattern + + # Store what keyword arguments are needed. + _named_args[args_key] = args_needed + + return compiled_pattern + +def _compile_replacement_helper(pattern, template): + "Compiles a replacement template." + # This function is called by the _regex module. + + # Have we seen this before? + key = pattern.pattern, pattern.flags, template + compiled = _replacement_cache.get(key) + if compiled is not None: + return compiled + + if len(_replacement_cache) >= _MAXREPCACHE: + _replacement_cache.clear() + + is_unicode = isinstance(template, str) + source = _Source(template) + if is_unicode: + def make_string(char_codes): + return "".join(chr(c) for c in char_codes) + else: + def make_string(char_codes): + return bytes(char_codes) + + compiled = [] + literal = [] + while True: + ch = source.get() + if not ch: + break + if ch == "\\": + # '_compile_replacement' will return either an int group reference + # or a string literal. It returns items (plural) in order to handle + # a 2-character literal (an invalid escape sequence). + is_group, items = _compile_replacement(source, pattern, is_unicode) + if is_group: + # It's a group, so first flush the literal. + if literal: + compiled.append(make_string(literal)) + literal = [] + compiled.extend(items) + else: + literal.extend(items) + else: + literal.append(ord(ch)) + + # Flush the literal. + if literal: + compiled.append(make_string(literal)) + + _replacement_cache[key] = compiled + + return compiled + +# We define Pattern here after all the support objects have been defined. +_pat = _compile('', 0, False, {}, False) +Pattern = type(_pat) +Match = type(_pat.match('')) +del _pat + +# Make Pattern public for typing annotations. +__all__.append("Pattern") +__all__.append("Match") + +# We'll define an alias for the 'compile' function so that the repr of a +# pattern object is eval-able. +Regex = compile + +# Register myself for pickling. +import copyreg as _copy_reg + +def _pickle(pattern): + return _regex.compile, pattern._pickled_data + +_copy_reg.pickle(Pattern, _pickle) \ No newline at end of file diff --git a/opteryx/third_party/mrabarnett/test_regex.py b/opteryx/third_party/mrabarnett/test_regex.py new file mode 100644 index 000000000..19372834c --- /dev/null +++ b/opteryx/third_party/mrabarnett/test_regex.py @@ -0,0 +1,4494 @@ +import os +import sys + +from weakref import proxy +import copy +import pickle +import string +import sys +import unittest + +sys.path.insert(1, os.path.join(sys.path[0], "../../..")) + +import regex + +# String subclasses for issue 18468. +class StrSubclass(str): + def __getitem__(self, index): + return StrSubclass(super().__getitem__(index)) + +class BytesSubclass(bytes): + def __getitem__(self, index): + return BytesSubclass(super().__getitem__(index)) + +class RegexTests(unittest.TestCase): + PATTERN_CLASS = "" + FLAGS_WITH_COMPILED_PAT = "cannot process flags argument with a compiled pattern" + INVALID_GROUP_REF = "invalid group reference" + MISSING_GT = "missing >" + BAD_GROUP_NAME = "bad character in group name" + MISSING_GROUP_NAME = "missing group name" + MISSING_LT = "missing <" + UNKNOWN_GROUP_I = "unknown group" + UNKNOWN_GROUP = "unknown group" + BAD_ESCAPE = r"bad escape \(end of pattern\)" + BAD_OCTAL_ESCAPE = r"bad escape \\" + BAD_SET = "unterminated character set" + STR_PAT_ON_BYTES = "cannot use a string pattern on a bytes-like object" + BYTES_PAT_ON_STR = "cannot use a bytes pattern on a string-like object" + STR_PAT_BYTES_TEMPL = "expected str instance, bytes found" + BYTES_PAT_STR_TEMPL = "expected a bytes-like object, str found" + BYTES_PAT_UNI_FLAG = "cannot use UNICODE flag with a bytes pattern" + MIXED_FLAGS = "ASCII, LOCALE and UNICODE flags are mutually incompatible" + MISSING_RPAREN = "missing \\)" + TRAILING_CHARS = "unbalanced parenthesis" + BAD_CHAR_RANGE = "bad character range" + NOTHING_TO_REPEAT = "nothing to repeat" + MULTIPLE_REPEAT = "multiple repeat" + OPEN_GROUP = "cannot refer to an open group" + DUPLICATE_GROUP = "duplicate group" + CANT_TURN_OFF = "bad inline flags: cannot turn flags off" + UNDEF_CHAR_NAME = "undefined character name" + + def assertTypedEqual(self, actual, expect, msg=None): + self.assertEqual(actual, expect, msg) + + def recurse(actual, expect): + if isinstance(expect, (tuple, list)): + for x, y in zip(actual, expect): + recurse(x, y) + else: + self.assertIs(type(actual), type(expect), msg) + + recurse(actual, expect) + + def test_weakref(self): + s = 'QabbbcR' + x = regex.compile('ab+c') + y = proxy(x) + if x.findall('QabbbcR') != y.findall('QabbbcR'): + self.fail() + + def test_search_star_plus(self): + self.assertEqual(regex.search('a*', 'xxx').span(0), (0, 0)) + self.assertEqual(regex.search('x*', 'axx').span(), (0, 0)) + self.assertEqual(regex.search('x+', 'axx').span(0), (1, 3)) + self.assertEqual(regex.search('x+', 'axx').span(), (1, 3)) + self.assertEqual(regex.search('x', 'aaa'), None) + self.assertEqual(regex.match('a*', 'xxx').span(0), (0, 0)) + self.assertEqual(regex.match('a*', 'xxx').span(), (0, 0)) + self.assertEqual(regex.match('x*', 'xxxa').span(0), (0, 3)) + self.assertEqual(regex.match('x*', 'xxxa').span(), (0, 3)) + self.assertEqual(regex.match('a+', 'xxx'), None) + + def bump_num(self, matchobj): + int_value = int(matchobj[0]) + return str(int_value + 1) + + def test_basic_regex_sub(self): + self.assertEqual(regex.sub("(?i)b+", "x", "bbbb BBBB"), 'x x') + self.assertEqual(regex.sub(r'\d+', self.bump_num, '08.2 -2 23x99y'), + '9.3 -3 24x100y') + self.assertEqual(regex.sub(r'\d+', self.bump_num, '08.2 -2 23x99y', 3), + '9.3 -3 23x99y') + + self.assertEqual(regex.sub('.', lambda m: r"\n", 'x'), "\\n") + self.assertEqual(regex.sub('.', r"\n", 'x'), "\n") + + self.assertEqual(regex.sub('(?Px)', r'\g\g', 'xx'), 'xxxx') + self.assertEqual(regex.sub('(?Px)', r'\g\g<1>', 'xx'), 'xxxx') + self.assertEqual(regex.sub('(?Px)', r'\g\g', 'xx'), + 'xxxx') + self.assertEqual(regex.sub('(?Px)', r'\g<1>\g<1>', 'xx'), 'xxxx') + + self.assertEqual(regex.sub('a', r'\t\n\v\r\f\a\b', 'a'), "\t\n\v\r\f\a\b") + self.assertEqual(regex.sub('a', '\t\n\v\r\f\a', 'a'), "\t\n\v\r\f\a") + self.assertEqual(regex.sub('a', '\t\n\v\r\f\a', 'a'), chr(9) + chr(10) + + chr(11) + chr(13) + chr(12) + chr(7)) + + self.assertEqual(regex.sub(r'^\s*', 'X', 'test'), 'Xtest') + + self.assertEqual(regex.sub(r"x", r"\x0A", "x"), "\n") + self.assertEqual(regex.sub(r"x", r"\u000A", "x"), "\n") + self.assertEqual(regex.sub(r"x", r"\U0000000A", "x"), "\n") + self.assertEqual(regex.sub(r"x", r"\N{LATIN CAPITAL LETTER A}", + "x"), "A") + + self.assertEqual(regex.sub(br"x", br"\x0A", b"x"), b"\n") + + def test_bug_449964(self): + # Fails for group followed by other escape. + self.assertEqual(regex.sub(r'(?Px)', r'\g<1>\g<1>\b', 'xx'), + "xx\bxx\b") + + def test_bug_449000(self): + # Test for sub() on escaped characters. + self.assertEqual(regex.sub(r'\r\n', r'\n', 'abc\r\ndef\r\n'), + "abc\ndef\n") + self.assertEqual(regex.sub('\r\n', r'\n', 'abc\r\ndef\r\n'), + "abc\ndef\n") + self.assertEqual(regex.sub(r'\r\n', '\n', 'abc\r\ndef\r\n'), + "abc\ndef\n") + self.assertEqual(regex.sub('\r\n', '\n', 'abc\r\ndef\r\n'), + "abc\ndef\n") + + def test_bug_1661(self): + # Verify that flags do not get silently ignored with compiled patterns + pattern = regex.compile('.') + self.assertRaisesRegex(ValueError, self.FLAGS_WITH_COMPILED_PAT, + lambda: regex.match(pattern, 'A', regex.I)) + self.assertRaisesRegex(ValueError, self.FLAGS_WITH_COMPILED_PAT, + lambda: regex.search(pattern, 'A', regex.I)) + self.assertRaisesRegex(ValueError, self.FLAGS_WITH_COMPILED_PAT, + lambda: regex.findall(pattern, 'A', regex.I)) + self.assertRaisesRegex(ValueError, self.FLAGS_WITH_COMPILED_PAT, + lambda: regex.compile(pattern, regex.I)) + + def test_bug_3629(self): + # A regex that triggered a bug in the sre-code validator + self.assertEqual(repr(type(regex.compile("(?P)(?(quote))"))), + self.PATTERN_CLASS) + + def test_sub_template_numeric_escape(self): + # Bug 776311 and friends. + self.assertEqual(regex.sub('x', r'\0', 'x'), "\0") + self.assertEqual(regex.sub('x', r'\000', 'x'), "\000") + self.assertEqual(regex.sub('x', r'\001', 'x'), "\001") + self.assertEqual(regex.sub('x', r'\008', 'x'), "\0" + "8") + self.assertEqual(regex.sub('x', r'\009', 'x'), "\0" + "9") + self.assertEqual(regex.sub('x', r'\111', 'x'), "\111") + self.assertEqual(regex.sub('x', r'\117', 'x'), "\117") + + self.assertEqual(regex.sub('x', r'\1111', 'x'), "\1111") + self.assertEqual(regex.sub('x', r'\1111', 'x'), "\111" + "1") + + self.assertEqual(regex.sub('x', r'\00', 'x'), '\x00') + self.assertEqual(regex.sub('x', r'\07', 'x'), '\x07') + self.assertEqual(regex.sub('x', r'\08', 'x'), "\0" + "8") + self.assertEqual(regex.sub('x', r'\09', 'x'), "\0" + "9") + self.assertEqual(regex.sub('x', r'\0a', 'x'), "\0" + "a") + + self.assertEqual(regex.sub('x', r'\400', 'x'), "\u0100") + self.assertEqual(regex.sub('x', r'\777', 'x'), "\u01FF") + self.assertEqual(regex.sub(b'x', br'\400', b'x'), b"\x00") + self.assertEqual(regex.sub(b'x', br'\777', b'x'), b"\xFF") + + self.assertRaisesRegex(regex.error, self.INVALID_GROUP_REF, lambda: + regex.sub('x', r'\1', 'x')) + self.assertRaisesRegex(regex.error, self.INVALID_GROUP_REF, lambda: + regex.sub('x', r'\8', 'x')) + self.assertRaisesRegex(regex.error, self.INVALID_GROUP_REF, lambda: + regex.sub('x', r'\9', 'x')) + self.assertRaisesRegex(regex.error, self.INVALID_GROUP_REF, lambda: + regex.sub('x', r'\11', 'x')) + self.assertRaisesRegex(regex.error, self.INVALID_GROUP_REF, lambda: + regex.sub('x', r'\18', 'x')) + self.assertRaisesRegex(regex.error, self.INVALID_GROUP_REF, lambda: + regex.sub('x', r'\1a', 'x')) + self.assertRaisesRegex(regex.error, self.INVALID_GROUP_REF, lambda: + regex.sub('x', r'\90', 'x')) + self.assertRaisesRegex(regex.error, self.INVALID_GROUP_REF, lambda: + regex.sub('x', r'\99', 'x')) + self.assertRaisesRegex(regex.error, self.INVALID_GROUP_REF, lambda: + regex.sub('x', r'\118', 'x')) # r'\11' + '8' + self.assertRaisesRegex(regex.error, self.INVALID_GROUP_REF, lambda: + regex.sub('x', r'\11a', 'x')) + self.assertRaisesRegex(regex.error, self.INVALID_GROUP_REF, lambda: + regex.sub('x', r'\181', 'x')) # r'\18' + '1' + self.assertRaisesRegex(regex.error, self.INVALID_GROUP_REF, lambda: + regex.sub('x', r'\800', 'x')) # r'\80' + '0' + + # In Python 2.3 (etc), these loop endlessly in sre_parser.py. + self.assertEqual(regex.sub('(((((((((((x)))))))))))', r'\11', 'x'), + 'x') + self.assertEqual(regex.sub('((((((((((y))))))))))(.)', r'\118', 'xyz'), + 'xz8') + self.assertEqual(regex.sub('((((((((((y))))))))))(.)', r'\11a', 'xyz'), + 'xza') + + def test_qualified_re_sub(self): + self.assertEqual(regex.sub('a', 'b', 'aaaaa'), 'bbbbb') + self.assertEqual(regex.sub('a', 'b', 'aaaaa', 1), 'baaaa') + + def test_bug_114660(self): + self.assertEqual(regex.sub(r'(\S)\s+(\S)', r'\1 \2', 'hello there'), + 'hello there') + + def test_bug_462270(self): + # Test for empty sub() behaviour, see SF bug #462270 + if sys.version_info >= (3, 7, 0): + self.assertEqual(regex.sub('(?V0)x*', '-', 'abxd'), '-a-b--d-') + else: + self.assertEqual(regex.sub('(?V0)x*', '-', 'abxd'), '-a-b-d-') + self.assertEqual(regex.sub('(?V1)x*', '-', 'abxd'), '-a-b--d-') + self.assertEqual(regex.sub('x+', '-', 'abxd'), 'ab-d') + + def test_bug_14462(self): + # chr(255) is a valid identifier in Python 3. + group_name = '\xFF' + self.assertEqual(regex.search(r'(?P<' + group_name + '>a)', + 'abc').group(group_name), 'a') + + def test_symbolic_refs(self): + self.assertRaisesRegex(regex.error, self.MISSING_GT, lambda: + regex.sub('(?Px)', r'\gx)', r'\g<', 'xx')) + self.assertRaisesRegex(regex.error, self.MISSING_LT, lambda: + regex.sub('(?Px)', r'\g', 'xx')) + self.assertRaisesRegex(regex.error, self.BAD_GROUP_NAME, lambda: + regex.sub('(?Px)', r'\g', 'xx')) + self.assertRaisesRegex(regex.error, self.BAD_GROUP_NAME, lambda: + regex.sub('(?Px)', r'\g<1a1>', 'xx')) + self.assertRaisesRegex(IndexError, self.UNKNOWN_GROUP_I, lambda: + regex.sub('(?Px)', r'\g', 'xx')) + + # The new behaviour of unmatched but valid groups is to treat them like + # empty matches in the replacement template, like in Perl. + self.assertEqual(regex.sub('(?Px)|(?Py)', r'\g', 'xx'), '') + self.assertEqual(regex.sub('(?Px)|(?Py)', r'\2', 'xx'), '') + + # The old behaviour was to raise it as an IndexError. + self.assertRaisesRegex(regex.error, self.BAD_GROUP_NAME, lambda: + regex.sub('(?Px)', r'\g<-1>', 'xx')) + + def test_re_subn(self): + self.assertEqual(regex.subn("(?i)b+", "x", "bbbb BBBB"), ('x x', 2)) + self.assertEqual(regex.subn("b+", "x", "bbbb BBBB"), ('x BBBB', 1)) + self.assertEqual(regex.subn("b+", "x", "xyz"), ('xyz', 0)) + self.assertEqual(regex.subn("b*", "x", "xyz"), ('xxxyxzx', 4)) + self.assertEqual(regex.subn("b*", "x", "xyz", 2), ('xxxyz', 2)) + + def test_re_split(self): + self.assertEqual(regex.split(":", ":a:b::c"), ['', 'a', 'b', '', 'c']) + if sys.version_info >= (3, 7, 0): + self.assertEqual(regex.split(":*", ":a:b::c"), ['', '', 'a', '', + 'b', '', 'c', '']) + self.assertEqual(regex.split("(:*)", ":a:b::c"), ['', ':', '', '', + 'a', ':', '', '', 'b', '::', '', '', 'c', '', '']) + self.assertEqual(regex.split("(?::*)", ":a:b::c"), ['', '', 'a', + '', 'b', '', 'c', '']) + self.assertEqual(regex.split("(:)*", ":a:b::c"), ['', ':', '', + None, 'a', ':', '', None, 'b', ':', '', None, 'c', None, '']) + else: + self.assertEqual(regex.split(":*", ":a:b::c"), ['', 'a', 'b', 'c']) + self.assertEqual(regex.split("(:*)", ":a:b::c"), ['', ':', 'a', + ':', 'b', '::', 'c']) + self.assertEqual(regex.split("(?::*)", ":a:b::c"), ['', 'a', 'b', + 'c']) + self.assertEqual(regex.split("(:)*", ":a:b::c"), ['', ':', 'a', + ':', 'b', ':', 'c']) + self.assertEqual(regex.split("([b:]+)", ":a:b::c"), ['', ':', 'a', + ':b::', 'c']) + self.assertEqual(regex.split("(b)|(:+)", ":a:b::c"), ['', None, ':', + 'a', None, ':', '', 'b', None, '', None, '::', 'c']) + self.assertEqual(regex.split("(?:b)|(?::+)", ":a:b::c"), ['', 'a', '', + '', 'c']) + + self.assertEqual(regex.split("x", "xaxbxc"), ['', 'a', 'b', 'c']) + self.assertEqual([m for m in regex.splititer("x", "xaxbxc")], ['', 'a', + 'b', 'c']) + + self.assertEqual(regex.split("(?r)x", "xaxbxc"), ['c', 'b', 'a', '']) + self.assertEqual([m for m in regex.splititer("(?r)x", "xaxbxc")], ['c', + 'b', 'a', '']) + + self.assertEqual(regex.split("(x)|(y)", "xaxbxc"), ['', 'x', None, 'a', + 'x', None, 'b', 'x', None, 'c']) + self.assertEqual([m for m in regex.splititer("(x)|(y)", "xaxbxc")], + ['', 'x', None, 'a', 'x', None, 'b', 'x', None, 'c']) + + self.assertEqual(regex.split("(?r)(x)|(y)", "xaxbxc"), ['c', 'x', None, + 'b', 'x', None, 'a', 'x', None, '']) + self.assertEqual([m for m in regex.splititer("(?r)(x)|(y)", "xaxbxc")], + ['c', 'x', None, 'b', 'x', None, 'a', 'x', None, '']) + + self.assertEqual(regex.split(r"(?V1)\b", "a b c"), ['', 'a', ' ', 'b', + ' ', 'c', '']) + self.assertEqual(regex.split(r"(?V1)\m", "a b c"), ['', 'a ', 'b ', + 'c']) + self.assertEqual(regex.split(r"(?V1)\M", "a b c"), ['a', ' b', ' c', + '']) + + def test_qualified_re_split(self): + self.assertEqual(regex.split(":", ":a:b::c", 2), ['', 'a', 'b::c']) + self.assertEqual(regex.split(':', 'a:b:c:d', 2), ['a', 'b', 'c:d']) + self.assertEqual(regex.split("(:)", ":a:b::c", 2), ['', ':', 'a', ':', + 'b::c']) + + if sys.version_info >= (3, 7, 0): + self.assertEqual(regex.split("(:*)", ":a:b::c", 2), ['', ':', '', + '', 'a:b::c']) + else: + self.assertEqual(regex.split("(:*)", ":a:b::c", 2), ['', ':', 'a', + ':', 'b::c']) + + def test_re_findall(self): + self.assertEqual(regex.findall(":+", "abc"), []) + self.assertEqual(regex.findall(":+", "a:b::c:::d"), [':', '::', ':::']) + self.assertEqual(regex.findall("(:+)", "a:b::c:::d"), [':', '::', + ':::']) + self.assertEqual(regex.findall("(:)(:*)", "a:b::c:::d"), [(':', ''), + (':', ':'), (':', '::')]) + + self.assertEqual(regex.findall(r"\((?P.{0,5}?TEST)\)", + "(MY TEST)"), ["MY TEST"]) + self.assertEqual(regex.findall(r"\((?P.{0,3}?TEST)\)", + "(MY TEST)"), ["MY TEST"]) + self.assertEqual(regex.findall(r"\((?P.{0,3}?T)\)", "(MY T)"), + ["MY T"]) + + self.assertEqual(regex.findall(r"[^a]{2}[A-Z]", "\n S"), [' S']) + self.assertEqual(regex.findall(r"[^a]{2,3}[A-Z]", "\n S"), ['\n S']) + self.assertEqual(regex.findall(r"[^a]{2,3}[A-Z]", "\n S"), [' S']) + + self.assertEqual(regex.findall(r"X(Y[^Y]+?){1,2}( |Q)+DEF", + "XYABCYPPQ\nQ DEF"), [('YPPQ\n', ' ')]) + + self.assertEqual(regex.findall(r"(\nTest(\n+.+?){0,2}?)?\n+End", + "\nTest\nxyz\nxyz\nEnd"), [('\nTest\nxyz\nxyz', '\nxyz')]) + + def test_bug_117612(self): + self.assertEqual(regex.findall(r"(a|(b))", "aba"), [('a', ''), ('b', + 'b'), ('a', '')]) + + def test_re_match(self): + self.assertEqual(regex.match('a', 'a')[:], ('a',)) + self.assertEqual(regex.match('(a)', 'a')[:], ('a', 'a')) + self.assertEqual(regex.match(r'(a)', 'a')[0], 'a') + self.assertEqual(regex.match(r'(a)', 'a')[1], 'a') + self.assertEqual(regex.match(r'(a)', 'a').group(1, 1), ('a', 'a')) + + pat = regex.compile('((a)|(b))(c)?') + self.assertEqual(pat.match('a')[:], ('a', 'a', 'a', None, None)) + self.assertEqual(pat.match('b')[:], ('b', 'b', None, 'b', None)) + self.assertEqual(pat.match('ac')[:], ('ac', 'a', 'a', None, 'c')) + self.assertEqual(pat.match('bc')[:], ('bc', 'b', None, 'b', 'c')) + self.assertEqual(pat.match('bc')[:], ('bc', 'b', None, 'b', 'c')) + + # A single group. + m = regex.match('(a)', 'a') + self.assertEqual(m.group(), 'a') + self.assertEqual(m.group(0), 'a') + self.assertEqual(m.group(1), 'a') + self.assertEqual(m.group(1, 1), ('a', 'a')) + + pat = regex.compile('(?:(?Pa)|(?Pb))(?Pc)?') + self.assertEqual(pat.match('a').group(1, 2, 3), ('a', None, None)) + self.assertEqual(pat.match('b').group('a1', 'b2', 'c3'), (None, 'b', + None)) + self.assertEqual(pat.match('ac').group(1, 'b2', 3), ('a', None, 'c')) + + def test_re_groupref_exists(self): + self.assertEqual(regex.match(r'^(\()?([^()]+)(?(1)\))$', '(a)')[:], + ('(a)', '(', 'a')) + self.assertEqual(regex.match(r'^(\()?([^()]+)(?(1)\))$', 'a')[:], ('a', + None, 'a')) + self.assertEqual(regex.match(r'^(\()?([^()]+)(?(1)\))$', 'a)'), None) + self.assertEqual(regex.match(r'^(\()?([^()]+)(?(1)\))$', '(a'), None) + self.assertEqual(regex.match('^(?:(a)|c)((?(1)b|d))$', 'ab')[:], ('ab', + 'a', 'b')) + self.assertEqual(regex.match('^(?:(a)|c)((?(1)b|d))$', 'cd')[:], ('cd', + None, 'd')) + self.assertEqual(regex.match('^(?:(a)|c)((?(1)|d))$', 'cd')[:], ('cd', + None, 'd')) + self.assertEqual(regex.match('^(?:(a)|c)((?(1)|d))$', 'a')[:], ('a', + 'a', '')) + + # Tests for bug #1177831: exercise groups other than the first group. + p = regex.compile('(?Pa)(?Pb)?((?(g2)c|d))') + self.assertEqual(p.match('abc')[:], ('abc', 'a', 'b', 'c')) + self.assertEqual(p.match('ad')[:], ('ad', 'a', None, 'd')) + self.assertEqual(p.match('abd'), None) + self.assertEqual(p.match('ac'), None) + + def test_re_groupref(self): + self.assertEqual(regex.match(r'^(\|)?([^()]+)\1$', '|a|')[:], ('|a|', + '|', 'a')) + self.assertEqual(regex.match(r'^(\|)?([^()]+)\1?$', 'a')[:], ('a', + None, 'a')) + self.assertEqual(regex.match(r'^(\|)?([^()]+)\1$', 'a|'), None) + self.assertEqual(regex.match(r'^(\|)?([^()]+)\1$', '|a'), None) + self.assertEqual(regex.match(r'^(?:(a)|c)(\1)$', 'aa')[:], ('aa', 'a', + 'a')) + self.assertEqual(regex.match(r'^(?:(a)|c)(\1)?$', 'c')[:], ('c', None, + None)) + + self.assertEqual(regex.findall(r"(?i)(.{1,40}?),(.{1,40}?)(?:;)+(.{1,80}).{1,40}?\3(\ |;)+(.{1,80}?)\1", + "TEST, BEST; LEST ; Lest 123 Test, Best"), [('TEST', ' BEST', + ' LEST', ' ', '123 ')]) + + def test_groupdict(self): + self.assertEqual(regex.match('(?Pfirst) (?Psecond)', + 'first second').groupdict(), {'first': 'first', 'second': 'second'}) + + def test_expand(self): + self.assertEqual(regex.match("(?Pfirst) (?Psecond)", + "first second").expand(r"\2 \1 \g \g"), + 'second first second first') + + def test_repeat_minmax(self): + self.assertEqual(regex.match(r"^(\w){1}$", "abc"), None) + self.assertEqual(regex.match(r"^(\w){1}?$", "abc"), None) + self.assertEqual(regex.match(r"^(\w){1,2}$", "abc"), None) + self.assertEqual(regex.match(r"^(\w){1,2}?$", "abc"), None) + + self.assertEqual(regex.match(r"^(\w){3}$", "abc")[1], 'c') + self.assertEqual(regex.match(r"^(\w){1,3}$", "abc")[1], 'c') + self.assertEqual(regex.match(r"^(\w){1,4}$", "abc")[1], 'c') + self.assertEqual(regex.match(r"^(\w){3,4}?$", "abc")[1], 'c') + self.assertEqual(regex.match(r"^(\w){3}?$", "abc")[1], 'c') + self.assertEqual(regex.match(r"^(\w){1,3}?$", "abc")[1], 'c') + self.assertEqual(regex.match(r"^(\w){1,4}?$", "abc")[1], 'c') + self.assertEqual(regex.match(r"^(\w){3,4}?$", "abc")[1], 'c') + + self.assertEqual(regex.match("^x{1}$", "xxx"), None) + self.assertEqual(regex.match("^x{1}?$", "xxx"), None) + self.assertEqual(regex.match("^x{1,2}$", "xxx"), None) + self.assertEqual(regex.match("^x{1,2}?$", "xxx"), None) + + self.assertEqual(regex.match("^x{1}", "xxx")[0], 'x') + self.assertEqual(regex.match("^x{1}?", "xxx")[0], 'x') + self.assertEqual(regex.match("^x{0,1}", "xxx")[0], 'x') + self.assertEqual(regex.match("^x{0,1}?", "xxx")[0], '') + + self.assertEqual(bool(regex.match("^x{3}$", "xxx")), True) + self.assertEqual(bool(regex.match("^x{1,3}$", "xxx")), True) + self.assertEqual(bool(regex.match("^x{1,4}$", "xxx")), True) + self.assertEqual(bool(regex.match("^x{3,4}?$", "xxx")), True) + self.assertEqual(bool(regex.match("^x{3}?$", "xxx")), True) + self.assertEqual(bool(regex.match("^x{1,3}?$", "xxx")), True) + self.assertEqual(bool(regex.match("^x{1,4}?$", "xxx")), True) + self.assertEqual(bool(regex.match("^x{3,4}?$", "xxx")), True) + + self.assertEqual(regex.match("^x{}$", "xxx"), None) + self.assertEqual(bool(regex.match("^x{}$", "x{}")), True) + + def test_getattr(self): + self.assertEqual(regex.compile("(?i)(a)(b)").pattern, '(?i)(a)(b)') + self.assertEqual(regex.compile("(?i)(a)(b)").flags, regex.I | regex.U | + regex.DEFAULT_VERSION) + self.assertEqual(regex.compile(b"(?i)(a)(b)").flags, regex.A | regex.I + | regex.DEFAULT_VERSION) + self.assertEqual(regex.compile("(?i)(a)(b)").groups, 2) + self.assertEqual(regex.compile("(?i)(a)(b)").groupindex, {}) + + self.assertEqual(regex.compile("(?i)(?Pa)(?Pb)").groupindex, + {'first': 1, 'other': 2}) + + self.assertEqual(regex.match("(a)", "a").pos, 0) + self.assertEqual(regex.match("(a)", "a").endpos, 1) + + self.assertEqual(regex.search("b(c)", "abcdef").pos, 0) + self.assertEqual(regex.search("b(c)", "abcdef").endpos, 6) + self.assertEqual(regex.search("b(c)", "abcdef").span(), (1, 3)) + self.assertEqual(regex.search("b(c)", "abcdef").span(1), (2, 3)) + + self.assertEqual(regex.match("(a)", "a").string, 'a') + self.assertEqual(regex.match("(a)", "a").regs, ((0, 1), (0, 1))) + self.assertEqual(repr(type(regex.match("(a)", "a").re)), + self.PATTERN_CLASS) + + # Issue 14260. + p = regex.compile(r'abc(?Pdef)') + p.groupindex["n"] = 0 + self.assertEqual(p.groupindex["n"], 1) + + def test_special_escapes(self): + self.assertEqual(regex.search(r"\b(b.)\b", "abcd abc bcd bx")[1], 'bx') + self.assertEqual(regex.search(r"\B(b.)\B", "abc bcd bc abxd")[1], 'bx') + self.assertEqual(regex.search(br"\b(b.)\b", b"abcd abc bcd bx", + regex.LOCALE)[1], b'bx') + self.assertEqual(regex.search(br"\B(b.)\B", b"abc bcd bc abxd", + regex.LOCALE)[1], b'bx') + self.assertEqual(regex.search(r"\b(b.)\b", "abcd abc bcd bx", + regex.UNICODE)[1], 'bx') + self.assertEqual(regex.search(r"\B(b.)\B", "abc bcd bc abxd", + regex.UNICODE)[1], 'bx') + + self.assertEqual(regex.search(r"^abc$", "\nabc\n", regex.M)[0], 'abc') + self.assertEqual(regex.search(r"^\Aabc\Z$", "abc", regex.M)[0], 'abc') + self.assertEqual(regex.search(r"^\Aabc\Z$", "\nabc\n", regex.M), None) + + self.assertEqual(regex.search(br"\b(b.)\b", b"abcd abc bcd bx")[1], + b'bx') + self.assertEqual(regex.search(br"\B(b.)\B", b"abc bcd bc abxd")[1], + b'bx') + self.assertEqual(regex.search(br"^abc$", b"\nabc\n", regex.M)[0], + b'abc') + self.assertEqual(regex.search(br"^\Aabc\Z$", b"abc", regex.M)[0], + b'abc') + self.assertEqual(regex.search(br"^\Aabc\Z$", b"\nabc\n", regex.M), + None) + + self.assertEqual(regex.search(r"\d\D\w\W\s\S", "1aa! a")[0], '1aa! a') + self.assertEqual(regex.search(br"\d\D\w\W\s\S", b"1aa! a", + regex.LOCALE)[0], b'1aa! a') + self.assertEqual(regex.search(r"\d\D\w\W\s\S", "1aa! a", + regex.UNICODE)[0], '1aa! a') + + def test_bigcharset(self): + self.assertEqual(regex.match(r"([\u2222\u2223])", "\u2222")[1], + '\u2222') + self.assertEqual(regex.match(r"([\u2222\u2223])", "\u2222", + regex.UNICODE)[1], '\u2222') + self.assertEqual("".join(regex.findall(".", + "e\xe8\xe9\xea\xeb\u0113\u011b\u0117", flags=regex.UNICODE)), + 'e\xe8\xe9\xea\xeb\u0113\u011b\u0117') + self.assertEqual("".join(regex.findall(r"[e\xe8\xe9\xea\xeb\u0113\u011b\u0117]", + "e\xe8\xe9\xea\xeb\u0113\u011b\u0117", flags=regex.UNICODE)), + 'e\xe8\xe9\xea\xeb\u0113\u011b\u0117') + self.assertEqual("".join(regex.findall(r"e|\xe8|\xe9|\xea|\xeb|\u0113|\u011b|\u0117", + "e\xe8\xe9\xea\xeb\u0113\u011b\u0117", flags=regex.UNICODE)), + 'e\xe8\xe9\xea\xeb\u0113\u011b\u0117') + + def test_anyall(self): + self.assertEqual(regex.match("a.b", "a\nb", regex.DOTALL)[0], "a\nb") + self.assertEqual(regex.match("a.*b", "a\n\nb", regex.DOTALL)[0], + "a\n\nb") + + def test_non_consuming(self): + self.assertEqual(regex.match(r"(a(?=\s[^a]))", "a b")[1], 'a') + self.assertEqual(regex.match(r"(a(?=\s[^a]*))", "a b")[1], 'a') + self.assertEqual(regex.match(r"(a(?=\s[abc]))", "a b")[1], 'a') + self.assertEqual(regex.match(r"(a(?=\s[abc]*))", "a bc")[1], 'a') + self.assertEqual(regex.match(r"(a)(?=\s\1)", "a a")[1], 'a') + self.assertEqual(regex.match(r"(a)(?=\s\1*)", "a aa")[1], 'a') + self.assertEqual(regex.match(r"(a)(?=\s(abc|a))", "a a")[1], 'a') + + self.assertEqual(regex.match(r"(a(?!\s[^a]))", "a a")[1], 'a') + self.assertEqual(regex.match(r"(a(?!\s[abc]))", "a d")[1], 'a') + self.assertEqual(regex.match(r"(a)(?!\s\1)", "a b")[1], 'a') + self.assertEqual(regex.match(r"(a)(?!\s(abc|a))", "a b")[1], 'a') + + def test_ignore_case(self): + self.assertEqual(regex.match("abc", "ABC", regex.I)[0], 'ABC') + self.assertEqual(regex.match(b"abc", b"ABC", regex.I)[0], b'ABC') + + self.assertEqual(regex.match(r"(a\s[^a]*)", "a bb", regex.I)[1], + 'a bb') + self.assertEqual(regex.match(r"(a\s[abc])", "a b", regex.I)[1], 'a b') + self.assertEqual(regex.match(r"(a\s[abc]*)", "a bb", regex.I)[1], + 'a bb') + self.assertEqual(regex.match(r"((a)\s\2)", "a a", regex.I)[1], 'a a') + self.assertEqual(regex.match(r"((a)\s\2*)", "a aa", regex.I)[1], + 'a aa') + self.assertEqual(regex.match(r"((a)\s(abc|a))", "a a", regex.I)[1], + 'a a') + self.assertEqual(regex.match(r"((a)\s(abc|a)*)", "a aa", regex.I)[1], + 'a aa') + + # Issue 3511. + self.assertEqual(regex.match(r"[Z-a]", "_").span(), (0, 1)) + self.assertEqual(regex.match(r"(?i)[Z-a]", "_").span(), (0, 1)) + + self.assertEqual(bool(regex.match(r"(?i)nao", "nAo")), True) + self.assertEqual(bool(regex.match(r"(?i)n\xE3o", "n\xC3o")), True) + self.assertEqual(bool(regex.match(r"(?i)n\xE3o", "N\xC3O")), True) + self.assertEqual(bool(regex.match(r"(?i)s", "\u017F")), True) + + def test_case_folding(self): + self.assertEqual(regex.search(r"(?fi)ss", "SS").span(), (0, 2)) + self.assertEqual(regex.search(r"(?fi)SS", "ss").span(), (0, 2)) + self.assertEqual(regex.search(r"(?fi)SS", + "\N{LATIN SMALL LETTER SHARP S}").span(), (0, 1)) + self.assertEqual(regex.search(r"(?fi)\N{LATIN SMALL LETTER SHARP S}", + "SS").span(), (0, 2)) + + self.assertEqual(regex.search(r"(?fi)\N{LATIN SMALL LIGATURE ST}", + "ST").span(), (0, 2)) + self.assertEqual(regex.search(r"(?fi)ST", + "\N{LATIN SMALL LIGATURE ST}").span(), (0, 1)) + self.assertEqual(regex.search(r"(?fi)ST", + "\N{LATIN SMALL LIGATURE LONG S T}").span(), (0, 1)) + + self.assertEqual(regex.search(r"(?fi)SST", + "\N{LATIN SMALL LETTER SHARP S}t").span(), (0, 2)) + self.assertEqual(regex.search(r"(?fi)SST", + "s\N{LATIN SMALL LIGATURE LONG S T}").span(), (0, 2)) + self.assertEqual(regex.search(r"(?fi)SST", + "s\N{LATIN SMALL LIGATURE ST}").span(), (0, 2)) + self.assertEqual(regex.search(r"(?fi)\N{LATIN SMALL LIGATURE ST}", + "SST").span(), (1, 3)) + self.assertEqual(regex.search(r"(?fi)SST", + "s\N{LATIN SMALL LIGATURE ST}").span(), (0, 2)) + + self.assertEqual(regex.search(r"(?fi)FFI", + "\N{LATIN SMALL LIGATURE FFI}").span(), (0, 1)) + self.assertEqual(regex.search(r"(?fi)FFI", + "\N{LATIN SMALL LIGATURE FF}i").span(), (0, 2)) + self.assertEqual(regex.search(r"(?fi)FFI", + "f\N{LATIN SMALL LIGATURE FI}").span(), (0, 2)) + self.assertEqual(regex.search(r"(?fi)\N{LATIN SMALL LIGATURE FFI}", + "FFI").span(), (0, 3)) + self.assertEqual(regex.search(r"(?fi)\N{LATIN SMALL LIGATURE FF}i", + "FFI").span(), (0, 3)) + self.assertEqual(regex.search(r"(?fi)f\N{LATIN SMALL LIGATURE FI}", + "FFI").span(), (0, 3)) + + sigma = "\u03A3\u03C3\u03C2" + for ch1 in sigma: + for ch2 in sigma: + if not regex.match(r"(?fi)" + ch1, ch2): + self.fail() + + self.assertEqual(bool(regex.search(r"(?iV1)ff", "\uFB00\uFB01")), + True) + self.assertEqual(bool(regex.search(r"(?iV1)ff", "\uFB01\uFB00")), + True) + self.assertEqual(bool(regex.search(r"(?iV1)fi", "\uFB00\uFB01")), + True) + self.assertEqual(bool(regex.search(r"(?iV1)fi", "\uFB01\uFB00")), + True) + self.assertEqual(bool(regex.search(r"(?iV1)fffi", "\uFB00\uFB01")), + True) + self.assertEqual(bool(regex.search(r"(?iV1)f\uFB03", + "\uFB00\uFB01")), True) + self.assertEqual(bool(regex.search(r"(?iV1)ff", "\uFB00\uFB01")), + True) + self.assertEqual(bool(regex.search(r"(?iV1)fi", "\uFB00\uFB01")), + True) + self.assertEqual(bool(regex.search(r"(?iV1)fffi", "\uFB00\uFB01")), + True) + self.assertEqual(bool(regex.search(r"(?iV1)f\uFB03", + "\uFB00\uFB01")), True) + self.assertEqual(bool(regex.search(r"(?iV1)f\uFB01", "\uFB00i")), + True) + self.assertEqual(bool(regex.search(r"(?iV1)f\uFB01", "\uFB00i")), + True) + + self.assertEqual(regex.findall(r"(?iV0)\m(?:word){e<=3}\M(?ne", "affine", + options=["\N{LATIN SMALL LIGATURE FFI}"]).span(), (0, 6)) + self.assertEqual(regex.search(r"(?fi)a\Lne", + "a\N{LATIN SMALL LIGATURE FFI}ne", options=["ffi"]).span(), (0, 4)) + + def test_category(self): + self.assertEqual(regex.match(r"(\s)", " ")[1], ' ') + + def test_not_literal(self): + self.assertEqual(regex.search(r"\s([^a])", " b")[1], 'b') + self.assertEqual(regex.search(r"\s([^a]*)", " bb")[1], 'bb') + + def test_search_coverage(self): + self.assertEqual(regex.search(r"\s(b)", " b")[1], 'b') + self.assertEqual(regex.search(r"a\s", "a ")[0], 'a ') + + def test_re_escape(self): + p = "" + self.assertEqual(regex.escape(p), p) + for i in range(0, 256): + p += chr(i) + self.assertEqual(bool(regex.match(regex.escape(chr(i)), chr(i))), + True) + self.assertEqual(regex.match(regex.escape(chr(i)), chr(i)).span(), + (0, 1)) + + pat = regex.compile(regex.escape(p)) + self.assertEqual(pat.match(p).span(), (0, 256)) + + def test_re_escape_byte(self): + p = b"" + self.assertEqual(regex.escape(p), p) + for i in range(0, 256): + b = bytes([i]) + p += b + self.assertEqual(bool(regex.match(regex.escape(b), b)), True) + self.assertEqual(regex.match(regex.escape(b), b).span(), (0, 1)) + + pat = regex.compile(regex.escape(p)) + self.assertEqual(pat.match(p).span(), (0, 256)) + + def test_constants(self): + if regex.I != regex.IGNORECASE: + self.fail() + if regex.L != regex.LOCALE: + self.fail() + if regex.M != regex.MULTILINE: + self.fail() + if regex.S != regex.DOTALL: + self.fail() + if regex.X != regex.VERBOSE: + self.fail() + + def test_flags(self): + for flag in [regex.I, regex.M, regex.X, regex.S, regex.L]: + self.assertEqual(repr(type(regex.compile('^pattern$', flag))), + self.PATTERN_CLASS) + + def test_sre_character_literals(self): + for i in [0, 8, 16, 32, 64, 127, 128, 255]: + self.assertEqual(bool(regex.match(r"\%03o" % i, chr(i))), True) + self.assertEqual(bool(regex.match(r"\%03o0" % i, chr(i) + "0")), + True) + self.assertEqual(bool(regex.match(r"\%03o8" % i, chr(i) + "8")), + True) + self.assertEqual(bool(regex.match(r"\x%02x" % i, chr(i))), True) + self.assertEqual(bool(regex.match(r"\x%02x0" % i, chr(i) + "0")), + True) + self.assertEqual(bool(regex.match(r"\x%02xz" % i, chr(i) + "z")), + True) + + self.assertRaisesRegex(regex.error, self.INVALID_GROUP_REF, lambda: + regex.match(r"\911", "")) + + def test_sre_character_class_literals(self): + for i in [0, 8, 16, 32, 64, 127, 128, 255]: + self.assertEqual(bool(regex.match(r"[\%03o]" % i, chr(i))), True) + self.assertEqual(bool(regex.match(r"[\%03o0]" % i, chr(i))), True) + self.assertEqual(bool(regex.match(r"[\%03o8]" % i, chr(i))), True) + self.assertEqual(bool(regex.match(r"[\x%02x]" % i, chr(i))), True) + self.assertEqual(bool(regex.match(r"[\x%02x0]" % i, chr(i))), True) + self.assertEqual(bool(regex.match(r"[\x%02xz]" % i, chr(i))), True) + + self.assertRaisesRegex(regex.error, self.BAD_OCTAL_ESCAPE, lambda: + regex.match(r"[\911]", "")) + + def test_bug_113254(self): + self.assertEqual(regex.match(r'(a)|(b)', 'b').start(1), -1) + self.assertEqual(regex.match(r'(a)|(b)', 'b').end(1), -1) + self.assertEqual(regex.match(r'(a)|(b)', 'b').span(1), (-1, -1)) + + def test_bug_527371(self): + # Bug described in patches 527371/672491. + self.assertEqual(regex.match(r'(a)?a','a').lastindex, None) + self.assertEqual(regex.match(r'(a)(b)?b','ab').lastindex, 1) + self.assertEqual(regex.match(r'(?Pa)(?Pb)?b','ab').lastgroup, + 'a') + self.assertEqual(regex.match("(?Pa(b))", "ab").lastgroup, 'a') + self.assertEqual(regex.match("((a))", "a").lastindex, 1) + + def test_bug_545855(self): + # Bug 545855 -- This pattern failed to cause a compile error as it + # should, instead provoking a TypeError. + self.assertRaisesRegex(regex.error, self.BAD_SET, lambda: + regex.compile('foo[a-')) + + def test_bug_418626(self): + # Bugs 418626 at al. -- Testing Greg Chapman's addition of op code + # SRE_OP_MIN_REPEAT_ONE for eliminating recursion on simple uses of + # pattern '*?' on a long string. + self.assertEqual(regex.match('.*?c', 10000 * 'ab' + 'cd').end(0), + 20001) + self.assertEqual(regex.match('.*?cd', 5000 * 'ab' + 'c' + 5000 * 'ab' + + 'cde').end(0), 20003) + self.assertEqual(regex.match('.*?cd', 20000 * 'abc' + 'de').end(0), + 60001) + # Non-simple '*?' still used to hit the recursion limit, before the + # non-recursive scheme was implemented. + self.assertEqual(regex.search('(a|b)*?c', 10000 * 'ab' + 'cd').end(0), + 20001) + + def test_bug_612074(self): + pat = "[" + regex.escape("\u2039") + "]" + self.assertEqual(regex.compile(pat) and 1, 1) + + def test_stack_overflow(self): + # Nasty cases that used to overflow the straightforward recursive + # implementation of repeated groups. + self.assertEqual(regex.match('(x)*', 50000 * 'x')[1], 'x') + self.assertEqual(regex.match('(x)*y', 50000 * 'x' + 'y')[1], 'x') + self.assertEqual(regex.match('(x)*?y', 50000 * 'x' + 'y')[1], 'x') + + def test_scanner(self): + def s_ident(scanner, token): return token + def s_operator(scanner, token): return "op%s" % token + def s_float(scanner, token): return float(token) + def s_int(scanner, token): return int(token) + + scanner = regex.Scanner([(r"[a-zA-Z_]\w*", s_ident), (r"\d+\.\d*", + s_float), (r"\d+", s_int), (r"=|\+|-|\*|/", s_operator), (r"\s+", + None), ]) + + self.assertEqual(repr(type(scanner.scanner.scanner("").pattern)), + self.PATTERN_CLASS) + + self.assertEqual(scanner.scan("sum = 3*foo + 312.50 + bar"), (['sum', + 'op=', 3, 'op*', 'foo', 'op+', 312.5, 'op+', 'bar'], '')) + + def test_bug_448951(self): + # Bug 448951 (similar to 429357, but with single char match). + # (Also test greedy matches.) + for op in '', '?', '*': + self.assertEqual(regex.match(r'((.%s):)?z' % op, 'z')[:], ('z', + None, None)) + self.assertEqual(regex.match(r'((.%s):)?z' % op, 'a:z')[:], ('a:z', + 'a:', 'a')) + + def test_bug_725106(self): + # Capturing groups in alternatives in repeats. + self.assertEqual(regex.match('^((a)|b)*', 'abc')[:], ('ab', 'b', 'a')) + self.assertEqual(regex.match('^(([ab])|c)*', 'abc')[:], ('abc', 'c', + 'b')) + self.assertEqual(regex.match('^((d)|[ab])*', 'abc')[:], ('ab', 'b', + None)) + self.assertEqual(regex.match('^((a)c|[ab])*', 'abc')[:], ('ab', 'b', + None)) + self.assertEqual(regex.match('^((a)|b)*?c', 'abc')[:], ('abc', 'b', + 'a')) + self.assertEqual(regex.match('^(([ab])|c)*?d', 'abcd')[:], ('abcd', + 'c', 'b')) + self.assertEqual(regex.match('^((d)|[ab])*?c', 'abc')[:], ('abc', 'b', + None)) + self.assertEqual(regex.match('^((a)c|[ab])*?c', 'abc')[:], ('abc', 'b', + None)) + + def test_bug_725149(self): + # Mark_stack_base restoring before restoring marks. + self.assertEqual(regex.match('(a)(?:(?=(b)*)c)*', 'abb')[:], ('a', 'a', + None)) + self.assertEqual(regex.match('(a)((?!(b)*))*', 'abb')[:], ('a', 'a', + None, None)) + + def test_bug_764548(self): + # Bug 764548, regex.compile() barfs on str/unicode subclasses. + class my_unicode(str): pass + pat = regex.compile(my_unicode("abc")) + self.assertEqual(pat.match("xyz"), None) + + def test_finditer(self): + it = regex.finditer(r":+", "a:b::c:::d") + self.assertEqual([item[0] for item in it], [':', '::', ':::']) + + def test_bug_926075(self): + if regex.compile('bug_926075') is regex.compile(b'bug_926075'): + self.fail() + + def test_bug_931848(self): + pattern = "[\u002E\u3002\uFF0E\uFF61]" + self.assertEqual(regex.compile(pattern).split("a.b.c"), ['a', 'b', + 'c']) + + def test_bug_581080(self): + it = regex.finditer(r"\s", "a b") + self.assertEqual(next(it).span(), (1, 2)) + self.assertRaises(StopIteration, lambda: next(it)) + + scanner = regex.compile(r"\s").scanner("a b") + self.assertEqual(scanner.search().span(), (1, 2)) + self.assertEqual(scanner.search(), None) + + def test_bug_817234(self): + it = regex.finditer(r".*", "asdf") + self.assertEqual(next(it).span(), (0, 4)) + self.assertEqual(next(it).span(), (4, 4)) + self.assertRaises(StopIteration, lambda: next(it)) + + def test_empty_array(self): + # SF buf 1647541. + import array + for typecode in 'bBuhHiIlLfd': + a = array.array(typecode) + self.assertEqual(regex.compile(b"bla").match(a), None) + self.assertEqual(regex.compile(b"").match(a)[1 : ], ()) + + def test_inline_flags(self): + # Bug #1700. + upper_char = chr(0x1ea0) # Latin Capital Letter A with Dot Below + lower_char = chr(0x1ea1) # Latin Small Letter A with Dot Below + + p = regex.compile(upper_char, regex.I | regex.U) + self.assertEqual(bool(p.match(lower_char)), True) + + p = regex.compile(lower_char, regex.I | regex.U) + self.assertEqual(bool(p.match(upper_char)), True) + + p = regex.compile('(?i)' + upper_char, regex.U) + self.assertEqual(bool(p.match(lower_char)), True) + + p = regex.compile('(?i)' + lower_char, regex.U) + self.assertEqual(bool(p.match(upper_char)), True) + + p = regex.compile('(?iu)' + upper_char) + self.assertEqual(bool(p.match(lower_char)), True) + + p = regex.compile('(?iu)' + lower_char) + self.assertEqual(bool(p.match(upper_char)), True) + + # Changed to positional flags in regex 2023.12.23. + self.assertEqual(bool(regex.match(r"(?i)a", "A")), True) + self.assertEqual(regex.match(r"a(?i)", "A"), None) + + def test_dollar_matches_twice(self): + # $ matches the end of string, and just before the terminating \n. + pattern = regex.compile('$') + self.assertEqual(pattern.sub('#', 'a\nb\n'), 'a\nb#\n#') + self.assertEqual(pattern.sub('#', 'a\nb\nc'), 'a\nb\nc#') + self.assertEqual(pattern.sub('#', '\n'), '#\n#') + + pattern = regex.compile('$', regex.MULTILINE) + self.assertEqual(pattern.sub('#', 'a\nb\n' ), 'a#\nb#\n#') + self.assertEqual(pattern.sub('#', 'a\nb\nc'), 'a#\nb#\nc#') + self.assertEqual(pattern.sub('#', '\n'), '#\n#') + + def test_bytes_str_mixing(self): + # Mixing str and bytes is disallowed. + pat = regex.compile('.') + bpat = regex.compile(b'.') + self.assertRaisesRegex(TypeError, self.STR_PAT_ON_BYTES, lambda: + pat.match(b'b')) + self.assertRaisesRegex(TypeError, self.BYTES_PAT_ON_STR, lambda: + bpat.match('b')) + self.assertRaisesRegex(TypeError, self.STR_PAT_BYTES_TEMPL, lambda: + pat.sub(b'b', 'c')) + self.assertRaisesRegex(TypeError, self.STR_PAT_ON_BYTES, lambda: + pat.sub('b', b'c')) + self.assertRaisesRegex(TypeError, self.STR_PAT_ON_BYTES, lambda: + pat.sub(b'b', b'c')) + self.assertRaisesRegex(TypeError, self.BYTES_PAT_ON_STR, lambda: + bpat.sub(b'b', 'c')) + self.assertRaisesRegex(TypeError, self.BYTES_PAT_STR_TEMPL, lambda: + bpat.sub('b', b'c')) + self.assertRaisesRegex(TypeError, self.BYTES_PAT_ON_STR, lambda: + bpat.sub('b', 'c')) + + self.assertRaisesRegex(ValueError, self.BYTES_PAT_UNI_FLAG, lambda: + regex.compile(br'\w', regex.UNICODE)) + self.assertRaisesRegex(ValueError, self.BYTES_PAT_UNI_FLAG, lambda: + regex.compile(br'(?u)\w')) + self.assertRaisesRegex(ValueError, self.MIXED_FLAGS, lambda: + regex.compile(r'\w', regex.UNICODE | regex.ASCII)) + self.assertRaisesRegex(ValueError, self.MIXED_FLAGS, lambda: + regex.compile(r'(?u)\w', regex.ASCII)) + self.assertRaisesRegex(ValueError, self.MIXED_FLAGS, lambda: + regex.compile(r'(?a)\w', regex.UNICODE)) + self.assertRaisesRegex(ValueError, self.MIXED_FLAGS, lambda: + regex.compile(r'(?au)\w')) + + def test_ascii_and_unicode_flag(self): + # String patterns. + for flags in (0, regex.UNICODE): + pat = regex.compile('\xc0', flags | regex.IGNORECASE) + self.assertEqual(bool(pat.match('\xe0')), True) + pat = regex.compile(r'\w', flags) + self.assertEqual(bool(pat.match('\xe0')), True) + + pat = regex.compile('\xc0', regex.ASCII | regex.IGNORECASE) + self.assertEqual(pat.match('\xe0'), None) + pat = regex.compile('(?a)\xc0', regex.IGNORECASE) + self.assertEqual(pat.match('\xe0'), None) + pat = regex.compile(r'\w', regex.ASCII) + self.assertEqual(pat.match('\xe0'), None) + pat = regex.compile(r'(?a)\w') + self.assertEqual(pat.match('\xe0'), None) + + # Bytes patterns. + for flags in (0, regex.ASCII): + pat = regex.compile(b'\xc0', flags | regex.IGNORECASE) + self.assertEqual(pat.match(b'\xe0'), None) + pat = regex.compile(br'\w') + self.assertEqual(pat.match(b'\xe0'), None) + + self.assertRaisesRegex(ValueError, self.MIXED_FLAGS, lambda: + regex.compile(r'(?au)\w')) + + def test_subscripting_match(self): + m = regex.match(r'(?\w)', 'xy') + if not m: + self.fail("Failed: expected match but returned None") + elif not m or m[0] != m.group(0) or m[1] != m.group(1): + self.fail("Failed") + if not m: + self.fail("Failed: expected match but returned None") + elif m[:] != ('x', 'x'): + self.fail("Failed: expected \"('x', 'x')\" but got {} instead".format(ascii(m[:]))) + + def test_new_named_groups(self): + m0 = regex.match(r'(?P\w)', 'x') + m1 = regex.match(r'(?\w)', 'x') + if not (m0 and m1 and m0[:] == m1[:]): + self.fail("Failed") + + def test_properties(self): + self.assertEqual(regex.match(b'(?ai)\xC0', b'\xE0'), None) + self.assertEqual(regex.match(br'(?ai)\xC0', b'\xE0'), None) + self.assertEqual(regex.match(br'(?a)\w', b'\xE0'), None) + self.assertEqual(bool(regex.match(r'\w', '\xE0')), True) + + # Dropped the following test. It's not possible to determine what the + # correct result should be in the general case. +# self.assertEqual(bool(regex.match(br'(?L)\w', b'\xE0')), +# b'\xE0'.isalnum()) + + self.assertEqual(bool(regex.match(br'(?L)\d', b'0')), True) + self.assertEqual(bool(regex.match(br'(?L)\s', b' ')), True) + self.assertEqual(bool(regex.match(br'(?L)\w', b'a')), True) + self.assertEqual(regex.match(br'(?L)\d', b'?'), None) + self.assertEqual(regex.match(br'(?L)\s', b'?'), None) + self.assertEqual(regex.match(br'(?L)\w', b'?'), None) + + self.assertEqual(regex.match(br'(?L)\D', b'0'), None) + self.assertEqual(regex.match(br'(?L)\S', b' '), None) + self.assertEqual(regex.match(br'(?L)\W', b'a'), None) + self.assertEqual(bool(regex.match(br'(?L)\D', b'?')), True) + self.assertEqual(bool(regex.match(br'(?L)\S', b'?')), True) + self.assertEqual(bool(regex.match(br'(?L)\W', b'?')), True) + + self.assertEqual(bool(regex.match(r'\p{Cyrillic}', + '\N{CYRILLIC CAPITAL LETTER A}')), True) + self.assertEqual(bool(regex.match(r'(?i)\p{Cyrillic}', + '\N{CYRILLIC CAPITAL LETTER A}')), True) + self.assertEqual(bool(regex.match(r'\p{IsCyrillic}', + '\N{CYRILLIC CAPITAL LETTER A}')), True) + self.assertEqual(bool(regex.match(r'\p{Script=Cyrillic}', + '\N{CYRILLIC CAPITAL LETTER A}')), True) + self.assertEqual(bool(regex.match(r'\p{InCyrillic}', + '\N{CYRILLIC CAPITAL LETTER A}')), True) + self.assertEqual(bool(regex.match(r'\p{Block=Cyrillic}', + '\N{CYRILLIC CAPITAL LETTER A}')), True) + self.assertEqual(bool(regex.match(r'[[:Cyrillic:]]', + '\N{CYRILLIC CAPITAL LETTER A}')), True) + self.assertEqual(bool(regex.match(r'[[:IsCyrillic:]]', + '\N{CYRILLIC CAPITAL LETTER A}')), True) + self.assertEqual(bool(regex.match(r'[[:Script=Cyrillic:]]', + '\N{CYRILLIC CAPITAL LETTER A}')), True) + self.assertEqual(bool(regex.match(r'[[:InCyrillic:]]', + '\N{CYRILLIC CAPITAL LETTER A}')), True) + self.assertEqual(bool(regex.match(r'[[:Block=Cyrillic:]]', + '\N{CYRILLIC CAPITAL LETTER A}')), True) + + self.assertEqual(bool(regex.match(r'\P{Cyrillic}', + '\N{LATIN CAPITAL LETTER A}')), True) + self.assertEqual(bool(regex.match(r'\P{IsCyrillic}', + '\N{LATIN CAPITAL LETTER A}')), True) + self.assertEqual(bool(regex.match(r'\P{Script=Cyrillic}', + '\N{LATIN CAPITAL LETTER A}')), True) + self.assertEqual(bool(regex.match(r'\P{InCyrillic}', + '\N{LATIN CAPITAL LETTER A}')), True) + self.assertEqual(bool(regex.match(r'\P{Block=Cyrillic}', + '\N{LATIN CAPITAL LETTER A}')), True) + self.assertEqual(bool(regex.match(r'\p{^Cyrillic}', + '\N{LATIN CAPITAL LETTER A}')), True) + self.assertEqual(bool(regex.match(r'\p{^IsCyrillic}', + '\N{LATIN CAPITAL LETTER A}')), True) + self.assertEqual(bool(regex.match(r'\p{^Script=Cyrillic}', + '\N{LATIN CAPITAL LETTER A}')), True) + self.assertEqual(bool(regex.match(r'\p{^InCyrillic}', + '\N{LATIN CAPITAL LETTER A}')), True) + self.assertEqual(bool(regex.match(r'\p{^Block=Cyrillic}', + '\N{LATIN CAPITAL LETTER A}')), True) + self.assertEqual(bool(regex.match(r'[[:^Cyrillic:]]', + '\N{LATIN CAPITAL LETTER A}')), True) + self.assertEqual(bool(regex.match(r'[[:^IsCyrillic:]]', + '\N{LATIN CAPITAL LETTER A}')), True) + self.assertEqual(bool(regex.match(r'[[:^Script=Cyrillic:]]', + '\N{LATIN CAPITAL LETTER A}')), True) + self.assertEqual(bool(regex.match(r'[[:^InCyrillic:]]', + '\N{LATIN CAPITAL LETTER A}')), True) + self.assertEqual(bool(regex.match(r'[[:^Block=Cyrillic:]]', + '\N{LATIN CAPITAL LETTER A}')), True) + + self.assertEqual(bool(regex.match(r'\d', '0')), True) + self.assertEqual(bool(regex.match(r'\s', ' ')), True) + self.assertEqual(bool(regex.match(r'\w', 'A')), True) + self.assertEqual(regex.match(r"\d", "?"), None) + self.assertEqual(regex.match(r"\s", "?"), None) + self.assertEqual(regex.match(r"\w", "?"), None) + self.assertEqual(regex.match(r"\D", "0"), None) + self.assertEqual(regex.match(r"\S", " "), None) + self.assertEqual(regex.match(r"\W", "A"), None) + self.assertEqual(bool(regex.match(r'\D', '?')), True) + self.assertEqual(bool(regex.match(r'\S', '?')), True) + self.assertEqual(bool(regex.match(r'\W', '?')), True) + + self.assertEqual(bool(regex.match(r'\p{L}', 'A')), True) + self.assertEqual(bool(regex.match(r'\p{L}', 'a')), True) + self.assertEqual(bool(regex.match(r'\p{Lu}', 'A')), True) + self.assertEqual(bool(regex.match(r'\p{Ll}', 'a')), True) + + self.assertEqual(bool(regex.match(r'(?i)a', 'a')), True) + self.assertEqual(bool(regex.match(r'(?i)a', 'A')), True) + + self.assertEqual(bool(regex.match(r'\w', '0')), True) + self.assertEqual(bool(regex.match(r'\w', 'a')), True) + self.assertEqual(bool(regex.match(r'\w', '_')), True) + + self.assertEqual(regex.match(r"\X", "\xE0").span(), (0, 1)) + self.assertEqual(regex.match(r"\X", "a\u0300").span(), (0, 2)) + self.assertEqual(regex.findall(r"\X", + "a\xE0a\u0300e\xE9e\u0301"), ['a', '\xe0', 'a\u0300', 'e', + '\xe9', 'e\u0301']) + self.assertEqual(regex.findall(r"\X{3}", + "a\xE0a\u0300e\xE9e\u0301"), ['a\xe0a\u0300', 'e\xe9e\u0301']) + self.assertEqual(regex.findall(r"\X", "\r\r\n\u0301A\u0301"), + ['\r', '\r\n', '\u0301', 'A\u0301']) + + self.assertEqual(bool(regex.match(r'\p{Ll}', 'a')), True) + + chars_u = "-09AZaz_\u0393\u03b3" + chars_b = b"-09AZaz_" + word_set = set("Ll Lm Lo Lt Lu Mc Me Mn Nd Nl No Pc".split()) + + tests = [ + (r"\w", chars_u, "09AZaz_\u0393\u03b3"), + (r"[[:word:]]", chars_u, "09AZaz_\u0393\u03b3"), + (r"\W", chars_u, "-"), + (r"[[:^word:]]", chars_u, "-"), + (r"\d", chars_u, "09"), + (r"[[:digit:]]", chars_u, "09"), + (r"\D", chars_u, "-AZaz_\u0393\u03b3"), + (r"[[:^digit:]]", chars_u, "-AZaz_\u0393\u03b3"), + (r"[[:alpha:]]", chars_u, "AZaz\u0393\u03b3"), + (r"[[:^alpha:]]", chars_u, "-09_"), + (r"[[:alnum:]]", chars_u, "09AZaz\u0393\u03b3"), + (r"[[:^alnum:]]", chars_u, "-_"), + (r"[[:xdigit:]]", chars_u, "09Aa"), + (r"[[:^xdigit:]]", chars_u, "-Zz_\u0393\u03b3"), + (r"\p{InBasicLatin}", "a\xE1", "a"), + (r"\P{InBasicLatin}", "a\xE1", "\xE1"), + (r"(?i)\p{InBasicLatin}", "a\xE1", "a"), + (r"(?i)\P{InBasicLatin}", "a\xE1", "\xE1"), + + (br"(?L)\w", chars_b, b"09AZaz_"), + (br"(?L)[[:word:]]", chars_b, b"09AZaz_"), + (br"(?L)\W", chars_b, b"-"), + (br"(?L)[[:^word:]]", chars_b, b"-"), + (br"(?L)\d", chars_b, b"09"), + (br"(?L)[[:digit:]]", chars_b, b"09"), + (br"(?L)\D", chars_b, b"-AZaz_"), + (br"(?L)[[:^digit:]]", chars_b, b"-AZaz_"), + (br"(?L)[[:alpha:]]", chars_b, b"AZaz"), + (br"(?L)[[:^alpha:]]", chars_b, b"-09_"), + (br"(?L)[[:alnum:]]", chars_b, b"09AZaz"), + (br"(?L)[[:^alnum:]]", chars_b, b"-_"), + (br"(?L)[[:xdigit:]]", chars_b, b"09Aa"), + (br"(?L)[[:^xdigit:]]", chars_b, b"-Zz_"), + + (br"(?a)\w", chars_b, b"09AZaz_"), + (br"(?a)[[:word:]]", chars_b, b"09AZaz_"), + (br"(?a)\W", chars_b, b"-"), + (br"(?a)[[:^word:]]", chars_b, b"-"), + (br"(?a)\d", chars_b, b"09"), + (br"(?a)[[:digit:]]", chars_b, b"09"), + (br"(?a)\D", chars_b, b"-AZaz_"), + (br"(?a)[[:^digit:]]", chars_b, b"-AZaz_"), + (br"(?a)[[:alpha:]]", chars_b, b"AZaz"), + (br"(?a)[[:^alpha:]]", chars_b, b"-09_"), + (br"(?a)[[:alnum:]]", chars_b, b"09AZaz"), + (br"(?a)[[:^alnum:]]", chars_b, b"-_"), + (br"(?a)[[:xdigit:]]", chars_b, b"09Aa"), + (br"(?a)[[:^xdigit:]]", chars_b, b"-Zz_"), + ] + for pattern, chars, expected in tests: + try: + if chars[ : 0].join(regex.findall(pattern, chars)) != expected: + self.fail("Failed: {}".format(pattern)) + except Exception as e: + self.fail("Failed: {} raised {}".format(pattern, ascii(e))) + + self.assertEqual(bool(regex.match(r"\p{NumericValue=0}", "0")), + True) + self.assertEqual(bool(regex.match(r"\p{NumericValue=1/2}", + "\N{VULGAR FRACTION ONE HALF}")), True) + self.assertEqual(bool(regex.match(r"\p{NumericValue=0.5}", + "\N{VULGAR FRACTION ONE HALF}")), True) + + def test_word_class(self): + self.assertEqual(regex.findall(r"\w+", + " \u0939\u093f\u0928\u094d\u0926\u0940,"), + ['\u0939\u093f\u0928\u094d\u0926\u0940']) + self.assertEqual(regex.findall(r"\W+", + " \u0939\u093f\u0928\u094d\u0926\u0940,"), [' ', ',']) + self.assertEqual(regex.split(r"(?V1)\b", + " \u0939\u093f\u0928\u094d\u0926\u0940,"), [' ', + '\u0939\u093f\u0928\u094d\u0926\u0940', ',']) + self.assertEqual(regex.split(r"(?V1)\B", + " \u0939\u093f\u0928\u094d\u0926\u0940,"), ['', ' \u0939', + '\u093f', '\u0928', '\u094d', '\u0926', '\u0940,', '']) + + def test_search_anchor(self): + self.assertEqual(regex.findall(r"\G\w{2}", "abcd ef"), ['ab', 'cd']) + + def test_search_reverse(self): + self.assertEqual(regex.findall(r"(?r).", "abc"), ['c', 'b', 'a']) + self.assertEqual(regex.findall(r"(?r).", "abc", overlapped=True), ['c', + 'b', 'a']) + self.assertEqual(regex.findall(r"(?r)..", "abcde"), ['de', 'bc']) + self.assertEqual(regex.findall(r"(?r)..", "abcde", overlapped=True), + ['de', 'cd', 'bc', 'ab']) + self.assertEqual(regex.findall(r"(?r)(.)(-)(.)", "a-b-c", + overlapped=True), [("b", "-", "c"), ("a", "-", "b")]) + + self.assertEqual([m[0] for m in regex.finditer(r"(?r).", "abc")], ['c', + 'b', 'a']) + self.assertEqual([m[0] for m in regex.finditer(r"(?r)..", "abcde", + overlapped=True)], ['de', 'cd', 'bc', 'ab']) + self.assertEqual([m[0] for m in regex.finditer(r"(?r).", "abc")], ['c', + 'b', 'a']) + self.assertEqual([m[0] for m in regex.finditer(r"(?r)..", "abcde", + overlapped=True)], ['de', 'cd', 'bc', 'ab']) + + self.assertEqual(regex.findall(r"^|\w+", "foo bar"), ['', 'foo', + 'bar']) + self.assertEqual(regex.findall(r"(?V1)^|\w+", "foo bar"), ['', 'foo', + 'bar']) + self.assertEqual(regex.findall(r"(?r)^|\w+", "foo bar"), ['bar', 'foo', + '']) + self.assertEqual(regex.findall(r"(?rV1)^|\w+", "foo bar"), ['bar', + 'foo', '']) + + self.assertEqual([m[0] for m in regex.finditer(r"^|\w+", "foo bar")], + ['', 'foo', 'bar']) + self.assertEqual([m[0] for m in regex.finditer(r"(?V1)^|\w+", + "foo bar")], ['', 'foo', 'bar']) + self.assertEqual([m[0] for m in regex.finditer(r"(?r)^|\w+", + "foo bar")], ['bar', 'foo', '']) + self.assertEqual([m[0] for m in regex.finditer(r"(?rV1)^|\w+", + "foo bar")], ['bar', 'foo', '']) + + self.assertEqual(regex.findall(r"\G\w{2}", "abcd ef"), ['ab', 'cd']) + self.assertEqual(regex.findall(r".{2}(?<=\G.*)", "abcd"), ['ab', 'cd']) + self.assertEqual(regex.findall(r"(?r)\G\w{2}", "abcd ef"), []) + self.assertEqual(regex.findall(r"(?r)\w{2}\G", "abcd ef"), ['ef']) + + self.assertEqual(regex.findall(r"q*", "qqwe"), ['qq', '', '', '']) + self.assertEqual(regex.findall(r"(?V1)q*", "qqwe"), ['qq', '', '', '']) + self.assertEqual(regex.findall(r"(?r)q*", "qqwe"), ['', '', 'qq', '']) + self.assertEqual(regex.findall(r"(?rV1)q*", "qqwe"), ['', '', 'qq', + '']) + + self.assertEqual(regex.findall(".", "abcd", pos=1, endpos=3), ['b', + 'c']) + self.assertEqual(regex.findall(".", "abcd", pos=1, endpos=-1), ['b', + 'c']) + self.assertEqual([m[0] for m in regex.finditer(".", "abcd", pos=1, + endpos=3)], ['b', 'c']) + self.assertEqual([m[0] for m in regex.finditer(".", "abcd", pos=1, + endpos=-1)], ['b', 'c']) + + self.assertEqual([m[0] for m in regex.finditer("(?r).", "abcd", pos=1, + endpos=3)], ['c', 'b']) + self.assertEqual([m[0] for m in regex.finditer("(?r).", "abcd", pos=1, + endpos=-1)], ['c', 'b']) + self.assertEqual(regex.findall("(?r).", "abcd", pos=1, endpos=3), ['c', + 'b']) + self.assertEqual(regex.findall("(?r).", "abcd", pos=1, endpos=-1), + ['c', 'b']) + + self.assertEqual(regex.findall(r"[ab]", "aB", regex.I), ['a', 'B']) + self.assertEqual(regex.findall(r"(?r)[ab]", "aB", regex.I), ['B', 'a']) + + self.assertEqual(regex.findall(r"(?r).{2}", "abc"), ['bc']) + self.assertEqual(regex.findall(r"(?r).{2}", "abc", overlapped=True), + ['bc', 'ab']) + self.assertEqual(regex.findall(r"(\w+) (\w+)", + "first second third fourth fifth"), [('first', 'second'), ('third', + 'fourth')]) + self.assertEqual(regex.findall(r"(?r)(\w+) (\w+)", + "first second third fourth fifth"), [('fourth', 'fifth'), ('second', + 'third')]) + + self.assertEqual([m[0] for m in regex.finditer(r"(?r).{2}", "abc")], + ['bc']) + self.assertEqual([m[0] for m in regex.finditer(r"(?r).{2}", "abc", + overlapped=True)], ['bc', 'ab']) + self.assertEqual([m[0] for m in regex.finditer(r"(\w+) (\w+)", + "first second third fourth fifth")], ['first second', + 'third fourth']) + self.assertEqual([m[0] for m in regex.finditer(r"(?r)(\w+) (\w+)", + "first second third fourth fifth")], ['fourth fifth', + 'second third']) + + self.assertEqual(regex.search("abcdef", "abcdef").span(), (0, 6)) + self.assertEqual(regex.search("(?r)abcdef", "abcdef").span(), (0, 6)) + self.assertEqual(regex.search("(?i)abcdef", "ABCDEF").span(), (0, 6)) + self.assertEqual(regex.search("(?ir)abcdef", "ABCDEF").span(), (0, 6)) + + self.assertEqual(regex.sub(r"(.)", r"\1", "abc"), 'abc') + self.assertEqual(regex.sub(r"(?r)(.)", r"\1", "abc"), 'abc') + + def test_atomic(self): + # Issue 433030. + self.assertEqual(regex.search(r"(?>a*)a", "aa"), None) + + def test_possessive(self): + # Single-character non-possessive. + self.assertEqual(regex.search(r"a?a", "a").span(), (0, 1)) + self.assertEqual(regex.search(r"a*a", "aaa").span(), (0, 3)) + self.assertEqual(regex.search(r"a+a", "aaa").span(), (0, 3)) + self.assertEqual(regex.search(r"a{1,3}a", "aaa").span(), (0, 3)) + + # Multiple-character non-possessive. + self.assertEqual(regex.search(r"(?:ab)?ab", "ab").span(), (0, 2)) + self.assertEqual(regex.search(r"(?:ab)*ab", "ababab").span(), (0, 6)) + self.assertEqual(regex.search(r"(?:ab)+ab", "ababab").span(), (0, 6)) + self.assertEqual(regex.search(r"(?:ab){1,3}ab", "ababab").span(), (0, + 6)) + + # Single-character possessive. + self.assertEqual(regex.search(r"a?+a", "a"), None) + self.assertEqual(regex.search(r"a*+a", "aaa"), None) + self.assertEqual(regex.search(r"a++a", "aaa"), None) + self.assertEqual(regex.search(r"a{1,3}+a", "aaa"), None) + + # Multiple-character possessive. + self.assertEqual(regex.search(r"(?:ab)?+ab", "ab"), None) + self.assertEqual(regex.search(r"(?:ab)*+ab", "ababab"), None) + self.assertEqual(regex.search(r"(?:ab)++ab", "ababab"), None) + self.assertEqual(regex.search(r"(?:ab){1,3}+ab", "ababab"), None) + + def test_zerowidth(self): + # Issue 3262. + if sys.version_info >= (3, 7, 0): + self.assertEqual(regex.split(r"\b", "a b"), ['', 'a', ' ', 'b', + '']) + else: + self.assertEqual(regex.split(r"\b", "a b"), ['a b']) + self.assertEqual(regex.split(r"(?V1)\b", "a b"), ['', 'a', ' ', 'b', + '']) + + # Issue 1647489. + self.assertEqual(regex.findall(r"^|\w+", "foo bar"), ['', 'foo', + 'bar']) + self.assertEqual([m[0] for m in regex.finditer(r"^|\w+", "foo bar")], + ['', 'foo', 'bar']) + self.assertEqual(regex.findall(r"(?r)^|\w+", "foo bar"), ['bar', + 'foo', '']) + self.assertEqual([m[0] for m in regex.finditer(r"(?r)^|\w+", + "foo bar")], ['bar', 'foo', '']) + self.assertEqual(regex.findall(r"(?V1)^|\w+", "foo bar"), ['', 'foo', + 'bar']) + self.assertEqual([m[0] for m in regex.finditer(r"(?V1)^|\w+", + "foo bar")], ['', 'foo', 'bar']) + self.assertEqual(regex.findall(r"(?rV1)^|\w+", "foo bar"), ['bar', + 'foo', '']) + self.assertEqual([m[0] for m in regex.finditer(r"(?rV1)^|\w+", + "foo bar")], ['bar', 'foo', '']) + + if sys.version_info >= (3, 7, 0): + self.assertEqual(regex.split("", "xaxbxc"), ['', 'x', 'a', 'x', + 'b', 'x', 'c', '']) + self.assertEqual([m for m in regex.splititer("", "xaxbxc")], ['', + 'x', 'a', 'x', 'b', 'x', 'c', '']) + else: + self.assertEqual(regex.split("", "xaxbxc"), ['xaxbxc']) + self.assertEqual([m for m in regex.splititer("", "xaxbxc")], + ['xaxbxc']) + + if sys.version_info >= (3, 7, 0): + self.assertEqual(regex.split("(?r)", "xaxbxc"), ['', 'c', 'x', 'b', + 'x', 'a', 'x', '']) + self.assertEqual([m for m in regex.splititer("(?r)", "xaxbxc")], + ['', 'c', 'x', 'b', 'x', 'a', 'x', '']) + else: + self.assertEqual(regex.split("(?r)", "xaxbxc"), ['xaxbxc']) + self.assertEqual([m for m in regex.splititer("(?r)", "xaxbxc")], + ['xaxbxc']) + + self.assertEqual(regex.split("(?V1)", "xaxbxc"), ['', 'x', 'a', 'x', + 'b', 'x', 'c', '']) + self.assertEqual([m for m in regex.splititer("(?V1)", "xaxbxc")], ['', + 'x', 'a', 'x', 'b', 'x', 'c', '']) + + self.assertEqual(regex.split("(?rV1)", "xaxbxc"), ['', 'c', 'x', 'b', + 'x', 'a', 'x', '']) + self.assertEqual([m for m in regex.splititer("(?rV1)", "xaxbxc")], ['', + 'c', 'x', 'b', 'x', 'a', 'x', '']) + + def test_scoped_and_inline_flags(self): + # Issues 433028, 433024, 433027. + self.assertEqual(regex.search(r"(?i)Ab", "ab").span(), (0, 2)) + self.assertEqual(regex.search(r"(?i:A)b", "ab").span(), (0, 2)) + # Changed to positional flags in regex 2023.12.23. + self.assertEqual(regex.search(r"A(?i)b", "ab"), None) + + self.assertEqual(regex.search(r"(?V0)Ab", "ab"), None) + self.assertEqual(regex.search(r"(?V1)Ab", "ab"), None) + self.assertEqual(regex.search(r"(?-i)Ab", "ab", flags=regex.I), None) + self.assertEqual(regex.search(r"(?-i:A)b", "ab", flags=regex.I), None) + self.assertEqual(regex.search(r"A(?-i)b", "ab", flags=regex.I).span(), + (0, 2)) + + def test_repeated_repeats(self): + # Issue 2537. + self.assertEqual(regex.search(r"(?:a+)+", "aaa").span(), (0, 3)) + self.assertEqual(regex.search(r"(?:(?:ab)+c)+", "abcabc").span(), (0, + 6)) + + # Hg issue 286. + self.assertEqual(regex.search(r"(?:a+){2,}", "aaa").span(), (0, 3)) + + def test_lookbehind(self): + self.assertEqual(regex.search(r"123(?<=a\d+)", "a123").span(), (1, 4)) + self.assertEqual(regex.search(r"123(?<=a\d+)", "b123"), None) + self.assertEqual(regex.search(r"123(?= (3, 7, 0): + self.assertEqual(regex.sub(r"(?V0)(x)?(y)?", r"\2-\1", "xy"), + 'y-x-') + else: + self.assertEqual(regex.sub(r"(?V0)(x)?(y)?", r"\2-\1", "xy"), + 'y-x') + self.assertEqual(regex.sub(r"(?V1)(x)?(y)?", r"\2-\1", "xy"), 'y-x-') + if sys.version_info >= (3, 7, 0): + self.assertEqual(regex.sub(r"(?V0)(x)?(y)?", r"\2-\1", "x"), '-x-') + else: + self.assertEqual(regex.sub(r"(?V0)(x)?(y)?", r"\2-\1", "x"), '-x') + self.assertEqual(regex.sub(r"(?V1)(x)?(y)?", r"\2-\1", "x"), '-x-') + if sys.version_info >= (3, 7, 0): + self.assertEqual(regex.sub(r"(?V0)(x)?(y)?", r"\2-\1", "y"), 'y--') + else: + self.assertEqual(regex.sub(r"(?V0)(x)?(y)?", r"\2-\1", "y"), 'y-') + self.assertEqual(regex.sub(r"(?V1)(x)?(y)?", r"\2-\1", "y"), 'y--') + + def test_bug_10328 (self): + # Issue 10328. + pat = regex.compile(r'(?mV0)(?P[ \t]+\r*$)|(?P(?<=[^\n])\Z)') + if sys.version_info >= (3, 7, 0): + self.assertEqual(pat.subn(lambda m: '<' + m.lastgroup + '>', + 'foobar '), ('foobar', 2)) + else: + self.assertEqual(pat.subn(lambda m: '<' + m.lastgroup + '>', + 'foobar '), ('foobar', 1)) + self.assertEqual([m.group() for m in pat.finditer('foobar ')], [' ', + '']) + pat = regex.compile(r'(?mV1)(?P[ \t]+\r*$)|(?P(?<=[^\n])\Z)') + self.assertEqual(pat.subn(lambda m: '<' + m.lastgroup + '>', + 'foobar '), ('foobar', 2)) + self.assertEqual([m.group() for m in pat.finditer('foobar ')], [' ', + '']) + + def test_overlapped(self): + self.assertEqual(regex.findall(r"..", "abcde"), ['ab', 'cd']) + self.assertEqual(regex.findall(r"..", "abcde", overlapped=True), ['ab', + 'bc', 'cd', 'de']) + self.assertEqual(regex.findall(r"(?r)..", "abcde"), ['de', 'bc']) + self.assertEqual(regex.findall(r"(?r)..", "abcde", overlapped=True), + ['de', 'cd', 'bc', 'ab']) + self.assertEqual(regex.findall(r"(.)(-)(.)", "a-b-c", overlapped=True), + [("a", "-", "b"), ("b", "-", "c")]) + + self.assertEqual([m[0] for m in regex.finditer(r"..", "abcde")], ['ab', + 'cd']) + self.assertEqual([m[0] for m in regex.finditer(r"..", "abcde", + overlapped=True)], ['ab', 'bc', 'cd', 'de']) + self.assertEqual([m[0] for m in regex.finditer(r"(?r)..", "abcde")], + ['de', 'bc']) + self.assertEqual([m[0] for m in regex.finditer(r"(?r)..", "abcde", + overlapped=True)], ['de', 'cd', 'bc', 'ab']) + + self.assertEqual([m.groups() for m in regex.finditer(r"(.)(-)(.)", + "a-b-c", overlapped=True)], [("a", "-", "b"), ("b", "-", "c")]) + self.assertEqual([m.groups() for m in regex.finditer(r"(?r)(.)(-)(.)", + "a-b-c", overlapped=True)], [("b", "-", "c"), ("a", "-", "b")]) + + def test_splititer(self): + self.assertEqual(regex.split(r",", "a,b,,c,"), ['a', 'b', '', 'c', '']) + self.assertEqual([m for m in regex.splititer(r",", "a,b,,c,")], ['a', + 'b', '', 'c', '']) + + def test_grapheme(self): + self.assertEqual(regex.match(r"\X", "\xE0").span(), (0, 1)) + self.assertEqual(regex.match(r"\X", "a\u0300").span(), (0, 2)) + + self.assertEqual(regex.findall(r"\X", + "a\xE0a\u0300e\xE9e\u0301"), ['a', '\xe0', 'a\u0300', 'e', + '\xe9', 'e\u0301']) + self.assertEqual(regex.findall(r"\X{3}", + "a\xE0a\u0300e\xE9e\u0301"), ['a\xe0a\u0300', 'e\xe9e\u0301']) + self.assertEqual(regex.findall(r"\X", "\r\r\n\u0301A\u0301"), + ['\r', '\r\n', '\u0301', 'A\u0301']) + + def test_word_boundary(self): + text = 'The quick ("brown") fox can\'t jump 32.3 feet, right?' + self.assertEqual(regex.split(r'(?V1)\b', text), ['', 'The', ' ', + 'quick', ' ("', 'brown', '") ', 'fox', ' ', 'can', "'", 't', + ' ', 'jump', ' ', '32', '.', '3', ' ', 'feet', ', ', + 'right', '?']) + self.assertEqual(regex.split(r'(?V1w)\b', text), ['', 'The', ' ', + 'quick', ' ', '(', '"', 'brown', '"', ')', ' ', 'fox', ' ', + "can't", ' ', 'jump', ' ', '32.3', ' ', 'feet', ',', ' ', + 'right', '?', '']) + + text = "The fox" + self.assertEqual(regex.split(r'(?V1)\b', text), ['', 'The', ' ', + 'fox', '']) + self.assertEqual(regex.split(r'(?V1w)\b', text), ['', 'The', ' ', + 'fox', '']) + + text = "can't aujourd'hui l'objectif" + self.assertEqual(regex.split(r'(?V1)\b', text), ['', 'can', "'", + 't', ' ', 'aujourd', "'", 'hui', ' ', 'l', "'", 'objectif', + '']) + self.assertEqual(regex.split(r'(?V1w)\b', text), ['', "can't", ' ', + "aujourd'hui", ' ', "l'objectif", '']) + + def test_line_boundary(self): + self.assertEqual(regex.findall(r".+", "Line 1\nLine 2\n"), ["Line 1", + "Line 2"]) + self.assertEqual(regex.findall(r".+", "Line 1\rLine 2\r"), + ["Line 1\rLine 2\r"]) + self.assertEqual(regex.findall(r".+", "Line 1\r\nLine 2\r\n"), + ["Line 1\r", "Line 2\r"]) + self.assertEqual(regex.findall(r"(?w).+", "Line 1\nLine 2\n"), + ["Line 1", "Line 2"]) + self.assertEqual(regex.findall(r"(?w).+", "Line 1\rLine 2\r"), + ["Line 1", "Line 2"]) + self.assertEqual(regex.findall(r"(?w).+", "Line 1\r\nLine 2\r\n"), + ["Line 1", "Line 2"]) + + self.assertEqual(regex.search(r"^abc", "abc").start(), 0) + self.assertEqual(regex.search(r"^abc", "\nabc"), None) + self.assertEqual(regex.search(r"^abc", "\rabc"), None) + self.assertEqual(regex.search(r"(?w)^abc", "abc").start(), 0) + self.assertEqual(regex.search(r"(?w)^abc", "\nabc"), None) + self.assertEqual(regex.search(r"(?w)^abc", "\rabc"), None) + + self.assertEqual(regex.search(r"abc$", "abc").start(), 0) + self.assertEqual(regex.search(r"abc$", "abc\n").start(), 0) + self.assertEqual(regex.search(r"abc$", "abc\r"), None) + self.assertEqual(regex.search(r"(?w)abc$", "abc").start(), 0) + self.assertEqual(regex.search(r"(?w)abc$", "abc\n").start(), 0) + self.assertEqual(regex.search(r"(?w)abc$", "abc\r").start(), 0) + + self.assertEqual(regex.search(r"(?m)^abc", "abc").start(), 0) + self.assertEqual(regex.search(r"(?m)^abc", "\nabc").start(), 1) + self.assertEqual(regex.search(r"(?m)^abc", "\rabc"), None) + self.assertEqual(regex.search(r"(?mw)^abc", "abc").start(), 0) + self.assertEqual(regex.search(r"(?mw)^abc", "\nabc").start(), 1) + self.assertEqual(regex.search(r"(?mw)^abc", "\rabc").start(), 1) + + self.assertEqual(regex.search(r"(?m)abc$", "abc").start(), 0) + self.assertEqual(regex.search(r"(?m)abc$", "abc\n").start(), 0) + self.assertEqual(regex.search(r"(?m)abc$", "abc\r"), None) + self.assertEqual(regex.search(r"(?mw)abc$", "abc").start(), 0) + self.assertEqual(regex.search(r"(?mw)abc$", "abc\n").start(), 0) + self.assertEqual(regex.search(r"(?mw)abc$", "abc\r").start(), 0) + + def test_branch_reset(self): + self.assertEqual(regex.match(r"(?:(a)|(b))(c)", "ac").groups(), ('a', + None, 'c')) + self.assertEqual(regex.match(r"(?:(a)|(b))(c)", "bc").groups(), (None, + 'b', 'c')) + self.assertEqual(regex.match(r"(?:(?a)|(?b))(?c)", + "ac").groups(), ('a', None, 'c')) + self.assertEqual(regex.match(r"(?:(?a)|(?b))(?c)", + "bc").groups(), (None, 'b', 'c')) + + self.assertEqual(regex.match(r"(?a)(?:(?b)|(?c))(?d)", + "abd").groups(), ('a', 'b', None, 'd')) + self.assertEqual(regex.match(r"(?a)(?:(?b)|(?c))(?d)", + "acd").groups(), ('a', None, 'c', 'd')) + self.assertEqual(regex.match(r"(a)(?:(b)|(c))(d)", "abd").groups(), + ('a', 'b', None, 'd')) + + self.assertEqual(regex.match(r"(a)(?:(b)|(c))(d)", "acd").groups(), + ('a', None, 'c', 'd')) + self.assertEqual(regex.match(r"(a)(?|(b)|(b))(d)", "abd").groups(), + ('a', 'b', 'd')) + self.assertEqual(regex.match(r"(?|(?a)|(?b))(c)", "ac").groups(), + ('a', None, 'c')) + self.assertEqual(regex.match(r"(?|(?a)|(?b))(c)", "bc").groups(), + (None, 'b', 'c')) + self.assertEqual(regex.match(r"(?|(?a)|(?b))(c)", "ac").groups(), + ('a', 'c')) + + self.assertEqual(regex.match(r"(?|(?a)|(?b))(c)", "bc").groups(), + ('b', 'c')) + + self.assertEqual(regex.match(r"(?|(?a)(?b)|(?c)(?d))(e)", + "abe").groups(), ('a', 'b', 'e')) + self.assertEqual(regex.match(r"(?|(?a)(?b)|(?c)(?d))(e)", + "cde").groups(), ('d', 'c', 'e')) + self.assertEqual(regex.match(r"(?|(?a)(?b)|(?c)(d))(e)", + "abe").groups(), ('a', 'b', 'e')) + self.assertEqual(regex.match(r"(?|(?a)(?b)|(?c)(d))(e)", + "cde").groups(), ('d', 'c', 'e')) + self.assertEqual(regex.match(r"(?|(?a)(?b)|(c)(d))(e)", + "abe").groups(), ('a', 'b', 'e')) + self.assertEqual(regex.match(r"(?|(?a)(?b)|(c)(d))(e)", + "cde").groups(), ('c', 'd', 'e')) + + # Hg issue 87: Allow duplicate names of groups + self.assertEqual(regex.match(r"(?|(?a)(?b)|(c)(?d))(e)", + "abe").groups(), ("a", "b", "e")) + self.assertEqual(regex.match(r"(?|(?a)(?b)|(c)(?d))(e)", + "abe").capturesdict(), {"a": ["a"], "b": ["b"]}) + self.assertEqual(regex.match(r"(?|(?a)(?b)|(c)(?d))(e)", + "cde").groups(), ("d", None, "e")) + self.assertEqual(regex.match(r"(?|(?a)(?b)|(c)(?d))(e)", + "cde").capturesdict(), {"a": ["c", "d"], "b": []}) + + def test_set(self): + self.assertEqual(regex.match(r"[a]", "a").span(), (0, 1)) + self.assertEqual(regex.match(r"(?i)[a]", "A").span(), (0, 1)) + self.assertEqual(regex.match(r"[a-b]", r"a").span(), (0, 1)) + self.assertEqual(regex.match(r"(?i)[a-b]", r"A").span(), (0, 1)) + + self.assertEqual(regex.sub(r"(?V0)([][])", r"-", "a[b]c"), "a-b-c") + + self.assertEqual(regex.findall(r"[\p{Alpha}]", "a0"), ["a"]) + self.assertEqual(regex.findall(r"(?i)[\p{Alpha}]", "A0"), ["A"]) + + self.assertEqual(regex.findall(r"[a\p{Alpha}]", "ab0"), ["a", "b"]) + self.assertEqual(regex.findall(r"[a\P{Alpha}]", "ab0"), ["a", "0"]) + self.assertEqual(regex.findall(r"(?i)[a\p{Alpha}]", "ab0"), ["a", + "b"]) + self.assertEqual(regex.findall(r"(?i)[a\P{Alpha}]", "ab0"), ["a", + "0"]) + + self.assertEqual(regex.findall(r"[a-b\p{Alpha}]", "abC0"), ["a", + "b", "C"]) + self.assertEqual(regex.findall(r"(?i)[a-b\p{Alpha}]", "AbC0"), ["A", + "b", "C"]) + + self.assertEqual(regex.findall(r"[\p{Alpha}]", "a0"), ["a"]) + self.assertEqual(regex.findall(r"[\P{Alpha}]", "a0"), ["0"]) + self.assertEqual(regex.findall(r"[^\p{Alpha}]", "a0"), ["0"]) + self.assertEqual(regex.findall(r"[^\P{Alpha}]", "a0"), ["a"]) + + self.assertEqual("".join(regex.findall(r"[^\d-h]", "a^b12c-h")), + 'a^bc') + self.assertEqual("".join(regex.findall(r"[^\dh]", "a^b12c-h")), + 'a^bc-') + self.assertEqual("".join(regex.findall(r"[^h\s\db]", "a^b 12c-h")), + 'a^c-') + self.assertEqual("".join(regex.findall(r"[^b\w]", "a b")), ' ') + self.assertEqual("".join(regex.findall(r"[^b\S]", "a b")), ' ') + self.assertEqual("".join(regex.findall(r"[^8\d]", "a 1b2")), 'a b') + + all_chars = "".join(chr(c) for c in range(0x100)) + self.assertEqual(len(regex.findall(r"\p{ASCII}", all_chars)), 128) + self.assertEqual(len(regex.findall(r"\p{Letter}", all_chars)), + 117) + self.assertEqual(len(regex.findall(r"\p{Digit}", all_chars)), 10) + + # Set operators + self.assertEqual(len(regex.findall(r"(?V1)[\p{ASCII}&&\p{Letter}]", + all_chars)), 52) + self.assertEqual(len(regex.findall(r"(?V1)[\p{ASCII}&&\p{Alnum}&&\p{Letter}]", + all_chars)), 52) + self.assertEqual(len(regex.findall(r"(?V1)[\p{ASCII}&&\p{Alnum}&&\p{Digit}]", + all_chars)), 10) + self.assertEqual(len(regex.findall(r"(?V1)[\p{ASCII}&&\p{Cc}]", + all_chars)), 33) + self.assertEqual(len(regex.findall(r"(?V1)[\p{ASCII}&&\p{Graph}]", + all_chars)), 94) + self.assertEqual(len(regex.findall(r"(?V1)[\p{ASCII}--\p{Cc}]", + all_chars)), 95) + self.assertEqual(len(regex.findall(r"[\p{Letter}\p{Digit}]", + all_chars)), 127) + self.assertEqual(len(regex.findall(r"(?V1)[\p{Letter}||\p{Digit}]", + all_chars)), 127) + self.assertEqual(len(regex.findall(r"\p{HexDigit}", all_chars)), + 22) + self.assertEqual(len(regex.findall(r"(?V1)[\p{HexDigit}~~\p{Digit}]", + all_chars)), 12) + self.assertEqual(len(regex.findall(r"(?V1)[\p{Digit}~~\p{HexDigit}]", + all_chars)), 12) + + self.assertEqual(repr(type(regex.compile(r"(?V0)([][-])"))), + self.PATTERN_CLASS) + self.assertEqual(regex.findall(r"(?V1)[[a-z]--[aei]]", "abc"), ["b", + "c"]) + self.assertEqual(regex.findall(r"(?iV1)[[a-z]--[aei]]", "abc"), ["b", + "c"]) + self.assertEqual(regex.findall(r"(?V1)[\w--a]","abc"), ["b", "c"]) + self.assertEqual(regex.findall(r"(?iV1)[\w--a]","abc"), ["b", "c"]) + + def test_various(self): + tests = [ + # Test ?P< and ?P= extensions. + ('(?Pa)', '', '', regex.error, self.BAD_GROUP_NAME), # Begins with a digit. + ('(?Pa)', '', '', regex.error, self.BAD_GROUP_NAME), # Begins with an illegal char. + ('(?Pa)', '', '', regex.error, self.BAD_GROUP_NAME), # Begins with an illegal char. + + # Same tests, for the ?P= form. + ('(?Pa)(?P=foo_123', 'aa', '', regex.error, + self.MISSING_RPAREN), + ('(?Pa)(?P=1)', 'aa', '1', ascii('a')), + ('(?Pa)(?P=0)', 'aa', '', regex.error, + self.BAD_GROUP_NAME), + ('(?Pa)(?P=-1)', 'aa', '', regex.error, + self.BAD_GROUP_NAME), + ('(?Pa)(?P=!)', 'aa', '', regex.error, + self.BAD_GROUP_NAME), + ('(?Pa)(?P=foo_124)', 'aa', '', regex.error, + self.UNKNOWN_GROUP), # Backref to undefined group. + + ('(?Pa)', 'a', '1', ascii('a')), + ('(?Pa)(?P=foo_123)', 'aa', '1', ascii('a')), + + # Mal-formed \g in pattern treated as literal for compatibility. + (r'(?a)\ga)\g<1>', 'aa', '1', ascii('a')), + (r'(?a)\g', 'aa', '', ascii(None)), + (r'(?a)\g', 'aa', '', regex.error, + self.UNKNOWN_GROUP), # Backref to undefined group. + + ('(?a)', 'a', '1', ascii('a')), + (r'(?a)\g', 'aa', '1', ascii('a')), + + # Test octal escapes. + ('\\1', 'a', '', regex.error, self.INVALID_GROUP_REF), # Backreference. + ('[\\1]', '\1', '0', "'\\x01'"), # Character. + ('\\09', chr(0) + '9', '0', ascii(chr(0) + '9')), + ('\\141', 'a', '0', ascii('a')), + ('(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)(l)\\119', 'abcdefghijklk9', + '0,11', ascii(('abcdefghijklk9', 'k'))), + + # Test \0 is handled everywhere. + (r'\0', '\0', '0', ascii('\0')), + (r'[\0a]', '\0', '0', ascii('\0')), + (r'[a\0]', '\0', '0', ascii('\0')), + (r'[^a\0]', '\0', '', ascii(None)), + + # Test various letter escapes. + (r'\a[\b]\f\n\r\t\v', '\a\b\f\n\r\t\v', '0', + ascii('\a\b\f\n\r\t\v')), + (r'[\a][\b][\f][\n][\r][\t][\v]', '\a\b\f\n\r\t\v', '0', + ascii('\a\b\f\n\r\t\v')), + (r'\xff', '\377', '0', ascii(chr(255))), + + # New \x semantics. + (r'\x00ffffffffffffff', '\377', '', ascii(None)), + (r'\x00f', '\017', '', ascii(None)), + (r'\x00fe', '\376', '', ascii(None)), + + (r'\x00ff', '\377', '', ascii(None)), + (r'\t\n\v\r\f\a\g', '\t\n\v\r\f\ag', '0', ascii('\t\n\v\r\f\ag')), + ('\t\n\v\r\f\a\\g', '\t\n\v\r\f\ag', '0', ascii('\t\n\v\r\f\ag')), + (r'\t\n\v\r\f\a', '\t\n\v\r\f\a', '0', ascii(chr(9) + chr(10) + + chr(11) + chr(13) + chr(12) + chr(7))), + (r'[\t][\n][\v][\r][\f][\b]', '\t\n\v\r\f\b', '0', + ascii('\t\n\v\r\f\b')), + + (r"^\w+=(\\[\000-\277]|[^\n\\])*", + "SRC=eval.c g.c blah blah blah \\\\\n\tapes.c", '0', + ascii("SRC=eval.c g.c blah blah blah \\\\")), + + # Test that . only matches \n in DOTALL mode. + ('a.b', 'acb', '0', ascii('acb')), + ('a.b', 'a\nb', '', ascii(None)), + ('a.*b', 'acc\nccb', '', ascii(None)), + ('a.{4,5}b', 'acc\nccb', '', ascii(None)), + ('a.b', 'a\rb', '0', ascii('a\rb')), + # Changed to positional flags in regex 2023.12.23. + ('a.b(?s)', 'a\nb', '', ascii(None)), + ('(?s)a.b', 'a\nb', '0', ascii('a\nb')), + ('a.*(?s)b', 'acc\nccb', '', ascii(None)), + ('(?s)a.*b', 'acc\nccb', '0', ascii('acc\nccb')), + ('(?s)a.{4,5}b', 'acc\nccb', '0', ascii('acc\nccb')), + + (')', '', '', regex.error, self.TRAILING_CHARS), # Unmatched right bracket. + ('', '', '0', "''"), # Empty pattern. + ('abc', 'abc', '0', ascii('abc')), + ('abc', 'xbc', '', ascii(None)), + ('abc', 'axc', '', ascii(None)), + ('abc', 'abx', '', ascii(None)), + ('abc', 'xabcy', '0', ascii('abc')), + ('abc', 'ababc', '0', ascii('abc')), + ('ab*c', 'abc', '0', ascii('abc')), + ('ab*bc', 'abc', '0', ascii('abc')), + + ('ab*bc', 'abbc', '0', ascii('abbc')), + ('ab*bc', 'abbbbc', '0', ascii('abbbbc')), + ('ab+bc', 'abbc', '0', ascii('abbc')), + ('ab+bc', 'abc', '', ascii(None)), + ('ab+bc', 'abq', '', ascii(None)), + ('ab+bc', 'abbbbc', '0', ascii('abbbbc')), + ('ab?bc', 'abbc', '0', ascii('abbc')), + ('ab?bc', 'abc', '0', ascii('abc')), + ('ab?bc', 'abbbbc', '', ascii(None)), + ('ab?c', 'abc', '0', ascii('abc')), + + ('^abc$', 'abc', '0', ascii('abc')), + ('^abc$', 'abcc', '', ascii(None)), + ('^abc', 'abcc', '0', ascii('abc')), + ('^abc$', 'aabc', '', ascii(None)), + ('abc$', 'aabc', '0', ascii('abc')), + ('^', 'abc', '0', ascii('')), + ('$', 'abc', '0', ascii('')), + ('a.c', 'abc', '0', ascii('abc')), + ('a.c', 'axc', '0', ascii('axc')), + ('a.*c', 'axyzc', '0', ascii('axyzc')), + + ('a.*c', 'axyzd', '', ascii(None)), + ('a[bc]d', 'abc', '', ascii(None)), + ('a[bc]d', 'abd', '0', ascii('abd')), + ('a[b-d]e', 'abd', '', ascii(None)), + ('a[b-d]e', 'ace', '0', ascii('ace')), + ('a[b-d]', 'aac', '0', ascii('ac')), + ('a[-b]', 'a-', '0', ascii('a-')), + ('a[\\-b]', 'a-', '0', ascii('a-')), + ('a[b-]', 'a-', '0', ascii('a-')), + ('a[]b', '-', '', regex.error, self.BAD_SET), + + ('a[', '-', '', regex.error, self.BAD_SET), + ('a\\', '-', '', regex.error, self.BAD_ESCAPE), + ('abc)', '-', '', regex.error, self.TRAILING_CHARS), + ('(abc', '-', '', regex.error, self.MISSING_RPAREN), + ('a]', 'a]', '0', ascii('a]')), + ('a[]]b', 'a]b', '0', ascii('a]b')), + ('a[]]b', 'a]b', '0', ascii('a]b')), + ('a[^bc]d', 'aed', '0', ascii('aed')), + ('a[^bc]d', 'abd', '', ascii(None)), + ('a[^-b]c', 'adc', '0', ascii('adc')), + + ('a[^-b]c', 'a-c', '', ascii(None)), + ('a[^]b]c', 'a]c', '', ascii(None)), + ('a[^]b]c', 'adc', '0', ascii('adc')), + ('\\ba\\b', 'a-', '0', ascii('a')), + ('\\ba\\b', '-a', '0', ascii('a')), + ('\\ba\\b', '-a-', '0', ascii('a')), + ('\\by\\b', 'xy', '', ascii(None)), + ('\\by\\b', 'yz', '', ascii(None)), + ('\\by\\b', 'xyz', '', ascii(None)), + ('x\\b', 'xyz', '', ascii(None)), + + ('x\\B', 'xyz', '0', ascii('x')), + ('\\Bz', 'xyz', '0', ascii('z')), + ('z\\B', 'xyz', '', ascii(None)), + ('\\Bx', 'xyz', '', ascii(None)), + ('\\Ba\\B', 'a-', '', ascii(None)), + ('\\Ba\\B', '-a', '', ascii(None)), + ('\\Ba\\B', '-a-', '', ascii(None)), + ('\\By\\B', 'xy', '', ascii(None)), + ('\\By\\B', 'yz', '', ascii(None)), + ('\\By\\b', 'xy', '0', ascii('y')), + + ('\\by\\B', 'yz', '0', ascii('y')), + ('\\By\\B', 'xyz', '0', ascii('y')), + ('ab|cd', 'abc', '0', ascii('ab')), + ('ab|cd', 'abcd', '0', ascii('ab')), + ('()ef', 'def', '0,1', ascii(('ef', ''))), + ('$b', 'b', '', ascii(None)), + ('a\\(b', 'a(b', '', ascii(('a(b',))), + ('a\\(*b', 'ab', '0', ascii('ab')), + ('a\\(*b', 'a((b', '0', ascii('a((b')), + ('a\\\\b', 'a\\b', '0', ascii('a\\b')), + + ('((a))', 'abc', '0,1,2', ascii(('a', 'a', 'a'))), + ('(a)b(c)', 'abc', '0,1,2', ascii(('abc', 'a', 'c'))), + ('a+b+c', 'aabbabc', '0', ascii('abc')), + ('(a+|b)*', 'ab', '0,1', ascii(('ab', 'b'))), + ('(a+|b)+', 'ab', '0,1', ascii(('ab', 'b'))), + ('(a+|b)?', 'ab', '0,1', ascii(('a', 'a'))), + (')(', '-', '', regex.error, self.TRAILING_CHARS), + ('[^ab]*', 'cde', '0', ascii('cde')), + ('abc', '', '', ascii(None)), + ('a*', '', '0', ascii('')), + + ('a|b|c|d|e', 'e', '0', ascii('e')), + ('(a|b|c|d|e)f', 'ef', '0,1', ascii(('ef', 'e'))), + ('abcd*efg', 'abcdefg', '0', ascii('abcdefg')), + ('ab*', 'xabyabbbz', '0', ascii('ab')), + ('ab*', 'xayabbbz', '0', ascii('a')), + ('(ab|cd)e', 'abcde', '0,1', ascii(('cde', 'cd'))), + ('[abhgefdc]ij', 'hij', '0', ascii('hij')), + ('^(ab|cd)e', 'abcde', '', ascii(None)), + ('(abc|)ef', 'abcdef', '0,1', ascii(('ef', ''))), + ('(a|b)c*d', 'abcd', '0,1', ascii(('bcd', 'b'))), + + ('(ab|ab*)bc', 'abc', '0,1', ascii(('abc', 'a'))), + ('a([bc]*)c*', 'abc', '0,1', ascii(('abc', 'bc'))), + ('a([bc]*)(c*d)', 'abcd', '0,1,2', ascii(('abcd', 'bc', 'd'))), + ('a([bc]+)(c*d)', 'abcd', '0,1,2', ascii(('abcd', 'bc', 'd'))), + ('a([bc]*)(c+d)', 'abcd', '0,1,2', ascii(('abcd', 'b', 'cd'))), + ('a[bcd]*dcdcde', 'adcdcde', '0', ascii('adcdcde')), + ('a[bcd]+dcdcde', 'adcdcde', '', ascii(None)), + ('(ab|a)b*c', 'abc', '0,1', ascii(('abc', 'ab'))), + ('((a)(b)c)(d)', 'abcd', '1,2,3,4', ascii(('abc', 'a', 'b', 'd'))), + ('[a-zA-Z_][a-zA-Z0-9_]*', 'alpha', '0', ascii('alpha')), + + ('^a(bc+|b[eh])g|.h$', 'abh', '0,1', ascii(('bh', None))), + ('(bc+d$|ef*g.|h?i(j|k))', 'effgz', '0,1,2', ascii(('effgz', + 'effgz', None))), + ('(bc+d$|ef*g.|h?i(j|k))', 'ij', '0,1,2', ascii(('ij', 'ij', + 'j'))), + ('(bc+d$|ef*g.|h?i(j|k))', 'effg', '', ascii(None)), + ('(bc+d$|ef*g.|h?i(j|k))', 'bcdd', '', ascii(None)), + ('(bc+d$|ef*g.|h?i(j|k))', 'reffgz', '0,1,2', ascii(('effgz', + 'effgz', None))), + ('(((((((((a)))))))))', 'a', '0', ascii('a')), + ('multiple words of text', 'uh-uh', '', ascii(None)), + ('multiple words', 'multiple words, yeah', '0', + ascii('multiple words')), + ('(.*)c(.*)', 'abcde', '0,1,2', ascii(('abcde', 'ab', 'de'))), + + ('\\((.*), (.*)\\)', '(a, b)', '2,1', ascii(('b', 'a'))), + ('[k]', 'ab', '', ascii(None)), + ('a[-]?c', 'ac', '0', ascii('ac')), + ('(abc)\\1', 'abcabc', '1', ascii('abc')), + ('([a-c]*)\\1', 'abcabc', '1', ascii('abc')), + ('^(.+)?B', 'AB', '1', ascii('A')), + ('(a+).\\1$', 'aaaaa', '0,1', ascii(('aaaaa', 'aa'))), + ('^(a+).\\1$', 'aaaa', '', ascii(None)), + ('(abc)\\1', 'abcabc', '0,1', ascii(('abcabc', 'abc'))), + ('([a-c]+)\\1', 'abcabc', '0,1', ascii(('abcabc', 'abc'))), + + ('(a)\\1', 'aa', '0,1', ascii(('aa', 'a'))), + ('(a+)\\1', 'aa', '0,1', ascii(('aa', 'a'))), + ('(a+)+\\1', 'aa', '0,1', ascii(('aa', 'a'))), + ('(a).+\\1', 'aba', '0,1', ascii(('aba', 'a'))), + ('(a)ba*\\1', 'aba', '0,1', ascii(('aba', 'a'))), + ('(aa|a)a\\1$', 'aaa', '0,1', ascii(('aaa', 'a'))), + ('(a|aa)a\\1$', 'aaa', '0,1', ascii(('aaa', 'a'))), + ('(a+)a\\1$', 'aaa', '0,1', ascii(('aaa', 'a'))), + ('([abc]*)\\1', 'abcabc', '0,1', ascii(('abcabc', 'abc'))), + ('(a)(b)c|ab', 'ab', '0,1,2', ascii(('ab', None, None))), + + ('(a)+x', 'aaax', '0,1', ascii(('aaax', 'a'))), + ('([ac])+x', 'aacx', '0,1', ascii(('aacx', 'c'))), + ('([^/]*/)*sub1/', 'd:msgs/tdir/sub1/trial/away.cpp', '0,1', + ascii(('d:msgs/tdir/sub1/', 'tdir/'))), + ('([^.]*)\\.([^:]*):[T ]+(.*)', 'track1.title:TBlah blah blah', + '0,1,2,3', ascii(('track1.title:TBlah blah blah', 'track1', + 'title', 'Blah blah blah'))), + ('([^N]*N)+', 'abNNxyzN', '0,1', ascii(('abNNxyzN', 'xyzN'))), + ('([^N]*N)+', 'abNNxyz', '0,1', ascii(('abNN', 'N'))), + ('([abc]*)x', 'abcx', '0,1', ascii(('abcx', 'abc'))), + ('([abc]*)x', 'abc', '', ascii(None)), + ('([xyz]*)x', 'abcx', '0,1', ascii(('x', ''))), + ('(a)+b|aac', 'aac', '0,1', ascii(('aac', None))), + + # Test symbolic groups. + ('(?Paaa)a', 'aaaa', '', regex.error, self.BAD_GROUP_NAME), + ('(?Paaa)a', 'aaaa', '0,id', ascii(('aaaa', 'aaa'))), + ('(?Paa)(?P=id)', 'aaaa', '0,id', ascii(('aaaa', 'aa'))), + ('(?Paa)(?P=xd)', 'aaaa', '', regex.error, self.UNKNOWN_GROUP), + + # Character properties. + (r"\g", "g", '0', ascii('g')), + (r"\g<1>", "g", '', regex.error, self.INVALID_GROUP_REF), + (r"(.)\g<1>", "gg", '0', ascii('gg')), + (r"(.)\g<1>", "gg", '', ascii(('gg', 'g'))), + (r"\N", "N", '0', ascii('N')), + (r"\N{LATIN SMALL LETTER A}", "a", '0', ascii('a')), + (r"\p", "p", '0', ascii('p')), + (r"\p{Ll}", "a", '0', ascii('a')), + (r"\P", "P", '0', ascii('P')), + (r"\P{Lu}", "p", '0', ascii('p')), + + # All tests from Perl. + ('abc', 'abc', '0', ascii('abc')), + ('abc', 'xbc', '', ascii(None)), + ('abc', 'axc', '', ascii(None)), + ('abc', 'abx', '', ascii(None)), + ('abc', 'xabcy', '0', ascii('abc')), + ('abc', 'ababc', '0', ascii('abc')), + + ('ab*c', 'abc', '0', ascii('abc')), + ('ab*bc', 'abc', '0', ascii('abc')), + ('ab*bc', 'abbc', '0', ascii('abbc')), + ('ab*bc', 'abbbbc', '0', ascii('abbbbc')), + ('ab{0,}bc', 'abbbbc', '0', ascii('abbbbc')), + ('ab+bc', 'abbc', '0', ascii('abbc')), + ('ab+bc', 'abc', '', ascii(None)), + ('ab+bc', 'abq', '', ascii(None)), + ('ab{1,}bc', 'abq', '', ascii(None)), + ('ab+bc', 'abbbbc', '0', ascii('abbbbc')), + + ('ab{1,}bc', 'abbbbc', '0', ascii('abbbbc')), + ('ab{1,3}bc', 'abbbbc', '0', ascii('abbbbc')), + ('ab{3,4}bc', 'abbbbc', '0', ascii('abbbbc')), + ('ab{4,5}bc', 'abbbbc', '', ascii(None)), + ('ab?bc', 'abbc', '0', ascii('abbc')), + ('ab?bc', 'abc', '0', ascii('abc')), + ('ab{0,1}bc', 'abc', '0', ascii('abc')), + ('ab?bc', 'abbbbc', '', ascii(None)), + ('ab?c', 'abc', '0', ascii('abc')), + ('ab{0,1}c', 'abc', '0', ascii('abc')), + + ('^abc$', 'abc', '0', ascii('abc')), + ('^abc$', 'abcc', '', ascii(None)), + ('^abc', 'abcc', '0', ascii('abc')), + ('^abc$', 'aabc', '', ascii(None)), + ('abc$', 'aabc', '0', ascii('abc')), + ('^', 'abc', '0', ascii('')), + ('$', 'abc', '0', ascii('')), + ('a.c', 'abc', '0', ascii('abc')), + ('a.c', 'axc', '0', ascii('axc')), + ('a.*c', 'axyzc', '0', ascii('axyzc')), + + ('a.*c', 'axyzd', '', ascii(None)), + ('a[bc]d', 'abc', '', ascii(None)), + ('a[bc]d', 'abd', '0', ascii('abd')), + ('a[b-d]e', 'abd', '', ascii(None)), + ('a[b-d]e', 'ace', '0', ascii('ace')), + ('a[b-d]', 'aac', '0', ascii('ac')), + ('a[-b]', 'a-', '0', ascii('a-')), + ('a[b-]', 'a-', '0', ascii('a-')), + ('a[b-a]', '-', '', regex.error, self.BAD_CHAR_RANGE), + ('a[]b', '-', '', regex.error, self.BAD_SET), + + ('a[', '-', '', regex.error, self.BAD_SET), + ('a]', 'a]', '0', ascii('a]')), + ('a[]]b', 'a]b', '0', ascii('a]b')), + ('a[^bc]d', 'aed', '0', ascii('aed')), + ('a[^bc]d', 'abd', '', ascii(None)), + ('a[^-b]c', 'adc', '0', ascii('adc')), + ('a[^-b]c', 'a-c', '', ascii(None)), + ('a[^]b]c', 'a]c', '', ascii(None)), + ('a[^]b]c', 'adc', '0', ascii('adc')), + ('ab|cd', 'abc', '0', ascii('ab')), + + ('ab|cd', 'abcd', '0', ascii('ab')), + ('()ef', 'def', '0,1', ascii(('ef', ''))), + ('*a', '-', '', regex.error, self.NOTHING_TO_REPEAT), + ('(*)b', '-', '', regex.error, self.NOTHING_TO_REPEAT), + ('$b', 'b', '', ascii(None)), + ('a\\', '-', '', regex.error, self.BAD_ESCAPE), + ('a\\(b', 'a(b', '', ascii(('a(b',))), + ('a\\(*b', 'ab', '0', ascii('ab')), + ('a\\(*b', 'a((b', '0', ascii('a((b')), + ('a\\\\b', 'a\\b', '0', ascii('a\\b')), + + ('abc)', '-', '', regex.error, self.TRAILING_CHARS), + ('(abc', '-', '', regex.error, self.MISSING_RPAREN), + ('((a))', 'abc', '0,1,2', ascii(('a', 'a', 'a'))), + ('(a)b(c)', 'abc', '0,1,2', ascii(('abc', 'a', 'c'))), + ('a+b+c', 'aabbabc', '0', ascii('abc')), + ('a{1,}b{1,}c', 'aabbabc', '0', ascii('abc')), + ('a**', '-', '', regex.error, self.MULTIPLE_REPEAT), + ('a.+?c', 'abcabc', '0', ascii('abc')), + ('(a+|b)*', 'ab', '0,1', ascii(('ab', 'b'))), + ('(a+|b){0,}', 'ab', '0,1', ascii(('ab', 'b'))), + + ('(a+|b)+', 'ab', '0,1', ascii(('ab', 'b'))), + ('(a+|b){1,}', 'ab', '0,1', ascii(('ab', 'b'))), + ('(a+|b)?', 'ab', '0,1', ascii(('a', 'a'))), + ('(a+|b){0,1}', 'ab', '0,1', ascii(('a', 'a'))), + (')(', '-', '', regex.error, self.TRAILING_CHARS), + ('[^ab]*', 'cde', '0', ascii('cde')), + ('abc', '', '', ascii(None)), + ('a*', '', '0', ascii('')), + ('([abc])*d', 'abbbcd', '0,1', ascii(('abbbcd', 'c'))), + ('([abc])*bcd', 'abcd', '0,1', ascii(('abcd', 'a'))), + + ('a|b|c|d|e', 'e', '0', ascii('e')), + ('(a|b|c|d|e)f', 'ef', '0,1', ascii(('ef', 'e'))), + ('abcd*efg', 'abcdefg', '0', ascii('abcdefg')), + ('ab*', 'xabyabbbz', '0', ascii('ab')), + ('ab*', 'xayabbbz', '0', ascii('a')), + ('(ab|cd)e', 'abcde', '0,1', ascii(('cde', 'cd'))), + ('[abhgefdc]ij', 'hij', '0', ascii('hij')), + ('^(ab|cd)e', 'abcde', '', ascii(None)), + ('(abc|)ef', 'abcdef', '0,1', ascii(('ef', ''))), + ('(a|b)c*d', 'abcd', '0,1', ascii(('bcd', 'b'))), + + ('(ab|ab*)bc', 'abc', '0,1', ascii(('abc', 'a'))), + ('a([bc]*)c*', 'abc', '0,1', ascii(('abc', 'bc'))), + ('a([bc]*)(c*d)', 'abcd', '0,1,2', ascii(('abcd', 'bc', 'd'))), + ('a([bc]+)(c*d)', 'abcd', '0,1,2', ascii(('abcd', 'bc', 'd'))), + ('a([bc]*)(c+d)', 'abcd', '0,1,2', ascii(('abcd', 'b', 'cd'))), + ('a[bcd]*dcdcde', 'adcdcde', '0', ascii('adcdcde')), + ('a[bcd]+dcdcde', 'adcdcde', '', ascii(None)), + ('(ab|a)b*c', 'abc', '0,1', ascii(('abc', 'ab'))), + ('((a)(b)c)(d)', 'abcd', '1,2,3,4', ascii(('abc', 'a', 'b', 'd'))), + ('[a-zA-Z_][a-zA-Z0-9_]*', 'alpha', '0', ascii('alpha')), + + ('^a(bc+|b[eh])g|.h$', 'abh', '0,1', ascii(('bh', None))), + ('(bc+d$|ef*g.|h?i(j|k))', 'effgz', '0,1,2', ascii(('effgz', + 'effgz', None))), + ('(bc+d$|ef*g.|h?i(j|k))', 'ij', '0,1,2', ascii(('ij', 'ij', + 'j'))), + ('(bc+d$|ef*g.|h?i(j|k))', 'effg', '', ascii(None)), + ('(bc+d$|ef*g.|h?i(j|k))', 'bcdd', '', ascii(None)), + ('(bc+d$|ef*g.|h?i(j|k))', 'reffgz', '0,1,2', ascii(('effgz', + 'effgz', None))), + ('((((((((((a))))))))))', 'a', '10', ascii('a')), + ('((((((((((a))))))))))\\10', 'aa', '0', ascii('aa')), + + # Python does not have the same rules for \\41 so this is a syntax error + # ('((((((((((a))))))))))\\41', 'aa', '', ascii(None)), + # ('((((((((((a))))))))))\\41', 'a!', '0', ascii('a!')), + ('((((((((((a))))))))))\\41', '', '', regex.error, + self.INVALID_GROUP_REF), + ('(?i)((((((((((a))))))))))\\41', '', '', regex.error, + self.INVALID_GROUP_REF), + + ('(((((((((a)))))))))', 'a', '0', ascii('a')), + ('multiple words of text', 'uh-uh', '', ascii(None)), + ('multiple words', 'multiple words, yeah', '0', + ascii('multiple words')), + ('(.*)c(.*)', 'abcde', '0,1,2', ascii(('abcde', 'ab', 'de'))), + ('\\((.*), (.*)\\)', '(a, b)', '2,1', ascii(('b', 'a'))), + ('[k]', 'ab', '', ascii(None)), + ('a[-]?c', 'ac', '0', ascii('ac')), + ('(abc)\\1', 'abcabc', '1', ascii('abc')), + ('([a-c]*)\\1', 'abcabc', '1', ascii('abc')), + ('(?i)abc', 'ABC', '0', ascii('ABC')), + + ('(?i)abc', 'XBC', '', ascii(None)), + ('(?i)abc', 'AXC', '', ascii(None)), + ('(?i)abc', 'ABX', '', ascii(None)), + ('(?i)abc', 'XABCY', '0', ascii('ABC')), + ('(?i)abc', 'ABABC', '0', ascii('ABC')), + ('(?i)ab*c', 'ABC', '0', ascii('ABC')), + ('(?i)ab*bc', 'ABC', '0', ascii('ABC')), + ('(?i)ab*bc', 'ABBC', '0', ascii('ABBC')), + ('(?i)ab*?bc', 'ABBBBC', '0', ascii('ABBBBC')), + ('(?i)ab{0,}?bc', 'ABBBBC', '0', ascii('ABBBBC')), + + ('(?i)ab+?bc', 'ABBC', '0', ascii('ABBC')), + ('(?i)ab+bc', 'ABC', '', ascii(None)), + ('(?i)ab+bc', 'ABQ', '', ascii(None)), + ('(?i)ab{1,}bc', 'ABQ', '', ascii(None)), + ('(?i)ab+bc', 'ABBBBC', '0', ascii('ABBBBC')), + ('(?i)ab{1,}?bc', 'ABBBBC', '0', ascii('ABBBBC')), + ('(?i)ab{1,3}?bc', 'ABBBBC', '0', ascii('ABBBBC')), + ('(?i)ab{3,4}?bc', 'ABBBBC', '0', ascii('ABBBBC')), + ('(?i)ab{4,5}?bc', 'ABBBBC', '', ascii(None)), + ('(?i)ab??bc', 'ABBC', '0', ascii('ABBC')), + + ('(?i)ab??bc', 'ABC', '0', ascii('ABC')), + ('(?i)ab{0,1}?bc', 'ABC', '0', ascii('ABC')), + ('(?i)ab??bc', 'ABBBBC', '', ascii(None)), + ('(?i)ab??c', 'ABC', '0', ascii('ABC')), + ('(?i)ab{0,1}?c', 'ABC', '0', ascii('ABC')), + ('(?i)^abc$', 'ABC', '0', ascii('ABC')), + ('(?i)^abc$', 'ABCC', '', ascii(None)), + ('(?i)^abc', 'ABCC', '0', ascii('ABC')), + ('(?i)^abc$', 'AABC', '', ascii(None)), + ('(?i)abc$', 'AABC', '0', ascii('ABC')), + + ('(?i)^', 'ABC', '0', ascii('')), + ('(?i)$', 'ABC', '0', ascii('')), + ('(?i)a.c', 'ABC', '0', ascii('ABC')), + ('(?i)a.c', 'AXC', '0', ascii('AXC')), + ('(?i)a.*?c', 'AXYZC', '0', ascii('AXYZC')), + ('(?i)a.*c', 'AXYZD', '', ascii(None)), + ('(?i)a[bc]d', 'ABC', '', ascii(None)), + ('(?i)a[bc]d', 'ABD', '0', ascii('ABD')), + ('(?i)a[b-d]e', 'ABD', '', ascii(None)), + ('(?i)a[b-d]e', 'ACE', '0', ascii('ACE')), + + ('(?i)a[b-d]', 'AAC', '0', ascii('AC')), + ('(?i)a[-b]', 'A-', '0', ascii('A-')), + ('(?i)a[b-]', 'A-', '0', ascii('A-')), + ('(?i)a[b-a]', '-', '', regex.error, self.BAD_CHAR_RANGE), + ('(?i)a[]b', '-', '', regex.error, self.BAD_SET), + ('(?i)a[', '-', '', regex.error, self.BAD_SET), + ('(?i)a]', 'A]', '0', ascii('A]')), + ('(?i)a[]]b', 'A]B', '0', ascii('A]B')), + ('(?i)a[^bc]d', 'AED', '0', ascii('AED')), + ('(?i)a[^bc]d', 'ABD', '', ascii(None)), + + ('(?i)a[^-b]c', 'ADC', '0', ascii('ADC')), + ('(?i)a[^-b]c', 'A-C', '', ascii(None)), + ('(?i)a[^]b]c', 'A]C', '', ascii(None)), + ('(?i)a[^]b]c', 'ADC', '0', ascii('ADC')), + ('(?i)ab|cd', 'ABC', '0', ascii('AB')), + ('(?i)ab|cd', 'ABCD', '0', ascii('AB')), + ('(?i)()ef', 'DEF', '0,1', ascii(('EF', ''))), + ('(?i)*a', '-', '', regex.error, self.NOTHING_TO_REPEAT), + ('(?i)(*)b', '-', '', regex.error, self.NOTHING_TO_REPEAT), + ('(?i)$b', 'B', '', ascii(None)), + + ('(?i)a\\', '-', '', regex.error, self.BAD_ESCAPE), + ('(?i)a\\(b', 'A(B', '', ascii(('A(B',))), + ('(?i)a\\(*b', 'AB', '0', ascii('AB')), + ('(?i)a\\(*b', 'A((B', '0', ascii('A((B')), + ('(?i)a\\\\b', 'A\\B', '0', ascii('A\\B')), + ('(?i)abc)', '-', '', regex.error, self.TRAILING_CHARS), + ('(?i)(abc', '-', '', regex.error, self.MISSING_RPAREN), + ('(?i)((a))', 'ABC', '0,1,2', ascii(('A', 'A', 'A'))), + ('(?i)(a)b(c)', 'ABC', '0,1,2', ascii(('ABC', 'A', 'C'))), + ('(?i)a+b+c', 'AABBABC', '0', ascii('ABC')), + + ('(?i)a{1,}b{1,}c', 'AABBABC', '0', ascii('ABC')), + ('(?i)a**', '-', '', regex.error, self.MULTIPLE_REPEAT), + ('(?i)a.+?c', 'ABCABC', '0', ascii('ABC')), + ('(?i)a.*?c', 'ABCABC', '0', ascii('ABC')), + ('(?i)a.{0,5}?c', 'ABCABC', '0', ascii('ABC')), + ('(?i)(a+|b)*', 'AB', '0,1', ascii(('AB', 'B'))), + ('(?i)(a+|b){0,}', 'AB', '0,1', ascii(('AB', 'B'))), + ('(?i)(a+|b)+', 'AB', '0,1', ascii(('AB', 'B'))), + ('(?i)(a+|b){1,}', 'AB', '0,1', ascii(('AB', 'B'))), + ('(?i)(a+|b)?', 'AB', '0,1', ascii(('A', 'A'))), + + ('(?i)(a+|b){0,1}', 'AB', '0,1', ascii(('A', 'A'))), + ('(?i)(a+|b){0,1}?', 'AB', '0,1', ascii(('', None))), + ('(?i))(', '-', '', regex.error, self.TRAILING_CHARS), + ('(?i)[^ab]*', 'CDE', '0', ascii('CDE')), + ('(?i)abc', '', '', ascii(None)), + ('(?i)a*', '', '0', ascii('')), + ('(?i)([abc])*d', 'ABBBCD', '0,1', ascii(('ABBBCD', 'C'))), + ('(?i)([abc])*bcd', 'ABCD', '0,1', ascii(('ABCD', 'A'))), + ('(?i)a|b|c|d|e', 'E', '0', ascii('E')), + ('(?i)(a|b|c|d|e)f', 'EF', '0,1', ascii(('EF', 'E'))), + + ('(?i)abcd*efg', 'ABCDEFG', '0', ascii('ABCDEFG')), + ('(?i)ab*', 'XABYABBBZ', '0', ascii('AB')), + ('(?i)ab*', 'XAYABBBZ', '0', ascii('A')), + ('(?i)(ab|cd)e', 'ABCDE', '0,1', ascii(('CDE', 'CD'))), + ('(?i)[abhgefdc]ij', 'HIJ', '0', ascii('HIJ')), + ('(?i)^(ab|cd)e', 'ABCDE', '', ascii(None)), + ('(?i)(abc|)ef', 'ABCDEF', '0,1', ascii(('EF', ''))), + ('(?i)(a|b)c*d', 'ABCD', '0,1', ascii(('BCD', 'B'))), + ('(?i)(ab|ab*)bc', 'ABC', '0,1', ascii(('ABC', 'A'))), + ('(?i)a([bc]*)c*', 'ABC', '0,1', ascii(('ABC', 'BC'))), + + ('(?i)a([bc]*)(c*d)', 'ABCD', '0,1,2', ascii(('ABCD', 'BC', 'D'))), + ('(?i)a([bc]+)(c*d)', 'ABCD', '0,1,2', ascii(('ABCD', 'BC', 'D'))), + ('(?i)a([bc]*)(c+d)', 'ABCD', '0,1,2', ascii(('ABCD', 'B', 'CD'))), + ('(?i)a[bcd]*dcdcde', 'ADCDCDE', '0', ascii('ADCDCDE')), + ('(?i)a[bcd]+dcdcde', 'ADCDCDE', '', ascii(None)), + ('(?i)(ab|a)b*c', 'ABC', '0,1', ascii(('ABC', 'AB'))), + ('(?i)((a)(b)c)(d)', 'ABCD', '1,2,3,4', ascii(('ABC', 'A', 'B', + 'D'))), + ('(?i)[a-zA-Z_][a-zA-Z0-9_]*', 'ALPHA', '0', ascii('ALPHA')), + ('(?i)^a(bc+|b[eh])g|.h$', 'ABH', '0,1', ascii(('BH', None))), + ('(?i)(bc+d$|ef*g.|h?i(j|k))', 'EFFGZ', '0,1,2', ascii(('EFFGZ', + 'EFFGZ', None))), + + ('(?i)(bc+d$|ef*g.|h?i(j|k))', 'IJ', '0,1,2', ascii(('IJ', 'IJ', + 'J'))), + ('(?i)(bc+d$|ef*g.|h?i(j|k))', 'EFFG', '', ascii(None)), + ('(?i)(bc+d$|ef*g.|h?i(j|k))', 'BCDD', '', ascii(None)), + ('(?i)(bc+d$|ef*g.|h?i(j|k))', 'REFFGZ', '0,1,2', ascii(('EFFGZ', + 'EFFGZ', None))), + ('(?i)((((((((((a))))))))))', 'A', '10', ascii('A')), + ('(?i)((((((((((a))))))))))\\10', 'AA', '0', ascii('AA')), + #('(?i)((((((((((a))))))))))\\41', 'AA', '', ascii(None)), + #('(?i)((((((((((a))))))))))\\41', 'A!', '0', ascii('A!')), + ('(?i)(((((((((a)))))))))', 'A', '0', ascii('A')), + ('(?i)(?:(?:(?:(?:(?:(?:(?:(?:(?:(a))))))))))', 'A', '1', + ascii('A')), + ('(?i)(?:(?:(?:(?:(?:(?:(?:(?:(?:(a|b|c))))))))))', 'C', '1', + ascii('C')), + ('(?i)multiple words of text', 'UH-UH', '', ascii(None)), + + ('(?i)multiple words', 'MULTIPLE WORDS, YEAH', '0', + ascii('MULTIPLE WORDS')), + ('(?i)(.*)c(.*)', 'ABCDE', '0,1,2', ascii(('ABCDE', 'AB', 'DE'))), + ('(?i)\\((.*), (.*)\\)', '(A, B)', '2,1', ascii(('B', 'A'))), + ('(?i)[k]', 'AB', '', ascii(None)), + # ('(?i)abcd', 'ABCD', SUCCEED, 'found+"-"+\\found+"-"+\\\\found', ascii(ABCD-$&-\\ABCD)), + # ('(?i)a(bc)d', 'ABCD', SUCCEED, 'g1+"-"+\\g1+"-"+\\\\g1', ascii(BC-$1-\\BC)), + ('(?i)a[-]?c', 'AC', '0', ascii('AC')), + ('(?i)(abc)\\1', 'ABCABC', '1', ascii('ABC')), + ('(?i)([a-c]*)\\1', 'ABCABC', '1', ascii('ABC')), + ('a(?!b).', 'abad', '0', ascii('ad')), + ('a(?=d).', 'abad', '0', ascii('ad')), + ('a(?=c|d).', 'abad', '0', ascii('ad')), + + ('a(?:b|c|d)(.)', 'ace', '1', ascii('e')), + ('a(?:b|c|d)*(.)', 'ace', '1', ascii('e')), + ('a(?:b|c|d)+?(.)', 'ace', '1', ascii('e')), + ('a(?:b|(c|e){1,2}?|d)+?(.)', 'ace', '1,2', ascii(('c', 'e'))), + + # Lookbehind: split by : but not if it is escaped by -. + ('(?]*?b', 'a>b', '', ascii(None)), + # Bug 490573: minimizing repeat problem. + (r'^a*?$', 'foo', '', ascii(None)), + # Bug 470582: nested groups problem. + (r'^((a)c)?(ab)$', 'ab', '1,2,3', ascii((None, None, 'ab'))), + # Another minimizing repeat problem (capturing groups in assertions). + ('^([ab]*?)(?=(b)?)c', 'abc', '1,2', ascii(('ab', None))), + ('^([ab]*?)(?!(b))c', 'abc', '1,2', ascii(('ab', None))), + ('^([ab]*?)(?(.){0,2})d", "abcd").captures(1), + ['b', 'c']) + self.assertEqual(regex.search(r"(.)+", "a").captures(1), ['a']) + + def test_guards(self): + m = regex.search(r"(X.*?Y\s*){3}(X\s*)+AB:", + "XY\nX Y\nX Y\nXY\nXX AB:") + self.assertEqual(m.span(0, 1, 2), ((3, 21), (12, 15), (16, 18))) + + m = regex.search(r"(X.*?Y\s*){3,}(X\s*)+AB:", + "XY\nX Y\nX Y\nXY\nXX AB:") + self.assertEqual(m.span(0, 1, 2), ((0, 21), (12, 15), (16, 18))) + + m = regex.search(r'\d{4}(\s*\w)?\W*((?!\d)\w){2}', "9999XX") + self.assertEqual(m.span(0, 1, 2), ((0, 6), (-1, -1), (5, 6))) + + m = regex.search(r'A\s*?.*?(\n+.*?\s*?){0,2}\(X', 'A\n1\nS\n1 (X') + self.assertEqual(m.span(0, 1), ((0, 10), (5, 8))) + + m = regex.search(r'Derde\s*:', 'aaaaaa:\nDerde:') + self.assertEqual(m.span(), (8, 14)) + m = regex.search(r'Derde\s*:', 'aaaaa:\nDerde:') + self.assertEqual(m.span(), (7, 13)) + + def test_turkic(self): + # Turkish has dotted and dotless I/i. + pairs = "I=i;I=\u0131;i=\u0130" + + all_chars = set() + matching = set() + for pair in pairs.split(";"): + ch1, ch2 = pair.split("=") + all_chars.update((ch1, ch2)) + matching.add((ch1, ch1)) + matching.add((ch1, ch2)) + matching.add((ch2, ch1)) + matching.add((ch2, ch2)) + + for ch1 in all_chars: + for ch2 in all_chars: + m = regex.match(r"(?i)\A" + ch1 + r"\Z", ch2) + if m: + if (ch1, ch2) not in matching: + self.fail("{} matching {}".format(ascii(ch1), + ascii(ch2))) + else: + if (ch1, ch2) in matching: + self.fail("{} not matching {}".format(ascii(ch1), + ascii(ch2))) + + def test_named_lists(self): + options = ["one", "two", "three"] + self.assertEqual(regex.match(r"333\L444", "333one444", + bar=options).group(), "333one444") + self.assertEqual(regex.match(r"(?i)333\L444", "333TWO444", + bar=options).group(), "333TWO444") + self.assertEqual(regex.match(r"333\L444", "333four444", + bar=options), None) + + options = [b"one", b"two", b"three"] + self.assertEqual(regex.match(br"333\L444", b"333one444", + bar=options).group(), b"333one444") + self.assertEqual(regex.match(br"(?i)333\L444", b"333TWO444", + bar=options).group(), b"333TWO444") + self.assertEqual(regex.match(br"333\L444", b"333four444", + bar=options), None) + + self.assertEqual(repr(type(regex.compile(r"3\L4\L+5", + bar=["one", "two", "three"]))), self.PATTERN_CLASS) + + self.assertEqual(regex.findall(r"^\L", "solid QWERT", + options=set(['good', 'brilliant', '+s\\ol[i}d'])), []) + self.assertEqual(regex.findall(r"^\L", "+solid QWERT", + options=set(['good', 'brilliant', '+solid'])), ['+solid']) + + options = ["STRASSE"] + self.assertEqual(regex.match(r"(?fi)\L", + "stra\N{LATIN SMALL LETTER SHARP S}e", words=options).span(), (0, + 6)) + + options = ["STRASSE", "stress"] + self.assertEqual(regex.match(r"(?fi)\L", + "stra\N{LATIN SMALL LETTER SHARP S}e", words=options).span(), (0, + 6)) + + options = ["stra\N{LATIN SMALL LETTER SHARP S}e"] + self.assertEqual(regex.match(r"(?fi)\L", "STRASSE", + words=options).span(), (0, 7)) + + options = ["kit"] + self.assertEqual(regex.search(r"(?i)\L", "SKITS", + words=options).span(), (1, 4)) + self.assertEqual(regex.search(r"(?i)\L", + "SK\N{LATIN CAPITAL LETTER I WITH DOT ABOVE}TS", + words=options).span(), (1, 4)) + + self.assertEqual(regex.search(r"(?fi)\b(\w+) +\1\b", + " stra\N{LATIN SMALL LETTER SHARP S}e STRASSE ").span(), (1, 15)) + self.assertEqual(regex.search(r"(?fi)\b(\w+) +\1\b", + " STRASSE stra\N{LATIN SMALL LETTER SHARP S}e ").span(), (1, 15)) + + self.assertEqual(regex.search(r"^\L$", "", options=[]).span(), + (0, 0)) + + def test_fuzzy(self): + # Some tests borrowed from TRE library tests. + self.assertEqual(repr(type(regex.compile('(fou){s,e<=1}'))), + self.PATTERN_CLASS) + self.assertEqual(repr(type(regex.compile('(fuu){s}'))), + self.PATTERN_CLASS) + self.assertEqual(repr(type(regex.compile('(fuu){s,e}'))), + self.PATTERN_CLASS) + self.assertEqual(repr(type(regex.compile('(anaconda){1i+1d<1,s<=1}'))), + self.PATTERN_CLASS) + self.assertEqual(repr(type(regex.compile('(anaconda){1i+1d<1,s<=1,e<=10}'))), + self.PATTERN_CLASS) + self.assertEqual(repr(type(regex.compile('(anaconda){s<=1,e<=1,1i+1d<1}'))), + self.PATTERN_CLASS) + + text = 'molasses anaconda foo bar baz smith anderson ' + self.assertEqual(regex.search('(znacnda){s<=1,e<=3,1i+1d<1}', text), + None) + self.assertEqual(regex.search('(znacnda){s<=1,e<=3,1i+1d<2}', + text).span(0, 1), ((9, 17), (9, 17))) + self.assertEqual(regex.search('(ananda){1i+1d<2}', text), None) + self.assertEqual(regex.search(r"(?:\bznacnda){e<=2}", text)[0], + "anaconda") + self.assertEqual(regex.search(r"(?:\bnacnda){e<=2}", text)[0], + "anaconda") + + text = 'anaconda foo bar baz smith anderson' + self.assertEqual(regex.search('(fuu){i<=3,d<=3,e<=5}', text).span(0, + 1), ((0, 0), (0, 0))) + self.assertEqual(regex.search('(?b)(fuu){i<=3,d<=3,e<=5}', + text).span(0, 1), ((9, 10), (9, 10))) + self.assertEqual(regex.search('(fuu){i<=2,d<=2,e<=5}', text).span(0, + 1), ((7, 10), (7, 10))) + self.assertEqual(regex.search('(?e)(fuu){i<=2,d<=2,e<=5}', + text).span(0, 1), ((9, 10), (9, 10))) + self.assertEqual(regex.search('(fuu){i<=3,d<=3,e}', text).span(0, 1), + ((0, 0), (0, 0))) + self.assertEqual(regex.search('(?b)(fuu){i<=3,d<=3,e}', text).span(0, + 1), ((9, 10), (9, 10))) + + self.assertEqual(repr(type(regex.compile('(approximate){s<=3,1i+1d<3}'))), + self.PATTERN_CLASS) + + # No cost limit. + self.assertEqual(regex.search('(foobar){e}', + 'xirefoabralfobarxie').span(0, 1), ((0, 6), (0, 6))) + self.assertEqual(regex.search('(?e)(foobar){e}', + 'xirefoabralfobarxie').span(0, 1), ((0, 3), (0, 3))) + self.assertEqual(regex.search('(?b)(foobar){e}', + 'xirefoabralfobarxie').span(0, 1), ((11, 16), (11, 16))) + + # At most two errors. + self.assertEqual(regex.search('(foobar){e<=2}', + 'xirefoabrzlfd').span(0, 1), ((4, 9), (4, 9))) + self.assertEqual(regex.search('(foobar){e<=2}', 'xirefoabzlfd'), None) + + # At most two inserts or substitutions and max two errors total. + self.assertEqual(regex.search('(foobar){i<=2,s<=2,e<=2}', + 'oobargoobaploowap').span(0, 1), ((5, 11), (5, 11))) + + # Find best whole word match for "foobar". + self.assertEqual(regex.search('\\b(foobar){e}\\b', 'zfoobarz').span(0, + 1), ((0, 8), (0, 8))) + self.assertEqual(regex.search('\\b(foobar){e}\\b', + 'boing zfoobarz goobar woop').span(0, 1), ((0, 6), (0, 6))) + self.assertEqual(regex.search('(?b)\\b(foobar){e}\\b', + 'boing zfoobarz goobar woop').span(0, 1), ((15, 21), (15, 21))) + + # Match whole string, allow only 1 error. + self.assertEqual(regex.search('^(foobar){e<=1}$', 'foobar').span(0, 1), + ((0, 6), (0, 6))) + self.assertEqual(regex.search('^(foobar){e<=1}$', 'xfoobar').span(0, + 1), ((0, 7), (0, 7))) + self.assertEqual(regex.search('^(foobar){e<=1}$', 'foobarx').span(0, + 1), ((0, 7), (0, 7))) + self.assertEqual(regex.search('^(foobar){e<=1}$', 'fooxbar').span(0, + 1), ((0, 7), (0, 7))) + self.assertEqual(regex.search('^(foobar){e<=1}$', 'foxbar').span(0, 1), + ((0, 6), (0, 6))) + self.assertEqual(regex.search('^(foobar){e<=1}$', 'xoobar').span(0, 1), + ((0, 6), (0, 6))) + self.assertEqual(regex.search('^(foobar){e<=1}$', 'foobax').span(0, 1), + ((0, 6), (0, 6))) + self.assertEqual(regex.search('^(foobar){e<=1}$', 'oobar').span(0, 1), + ((0, 5), (0, 5))) + self.assertEqual(regex.search('^(foobar){e<=1}$', 'fobar').span(0, 1), + ((0, 5), (0, 5))) + self.assertEqual(regex.search('^(foobar){e<=1}$', 'fooba').span(0, 1), + ((0, 5), (0, 5))) + self.assertEqual(regex.search('^(foobar){e<=1}$', 'xfoobarx'), None) + self.assertEqual(regex.search('^(foobar){e<=1}$', 'foobarxx'), None) + self.assertEqual(regex.search('^(foobar){e<=1}$', 'xxfoobar'), None) + self.assertEqual(regex.search('^(foobar){e<=1}$', 'xfoxbar'), None) + self.assertEqual(regex.search('^(foobar){e<=1}$', 'foxbarx'), None) + + # At most one insert, two deletes, and three substitutions. + # Additionally, deletes cost two and substitutes one, and total + # cost must be less than 4. + self.assertEqual(regex.search('(foobar){i<=1,d<=2,s<=3,2d+1s<4}', + '3oifaowefbaoraofuiebofasebfaobfaorfeoaro').span(0, 1), ((6, 13), (6, + 13))) + self.assertEqual(regex.search('(?b)(foobar){i<=1,d<=2,s<=3,2d+1s<4}', + '3oifaowefbaoraofuiebofasebfaobfaorfeoaro').span(0, 1), ((34, 39), + (34, 39))) + + # Partially fuzzy matches. + self.assertEqual(regex.search('foo(bar){e<=1}zap', 'foobarzap').span(0, + 1), ((0, 9), (3, 6))) + self.assertEqual(regex.search('foo(bar){e<=1}zap', 'fobarzap'), None) + self.assertEqual(regex.search('foo(bar){e<=1}zap', 'foobrzap').span(0, + 1), ((0, 8), (3, 5))) + + text = ('www.cnn.com 64.236.16.20\nwww.slashdot.org 66.35.250.150\n' + 'For useful information, use www.slashdot.org\nthis is demo data!\n') + self.assertEqual(regex.search(r'(?s)^.*(dot.org){e}.*$', text).span(0, + 1), ((0, 120), (120, 120))) + self.assertEqual(regex.search(r'(?es)^.*(dot.org){e}.*$', text).span(0, + 1), ((0, 120), (93, 100))) + self.assertEqual(regex.search(r'^.*(dot.org){e}.*$', text).span(0, 1), + ((0, 119), (24, 101))) + + # Behaviour is unexpected, but arguably not wrong. It first finds the + # best match, then the best in what follows, etc. + self.assertEqual(regex.findall(r"\b\L{e<=1}\b", + " book cot dog desk ", words="cat dog".split()), ["cot", "dog"]) + self.assertEqual(regex.findall(r"\b\L{e<=1}\b", + " book dog cot desk ", words="cat dog".split()), [" dog", "cot"]) + self.assertEqual(regex.findall(r"(?e)\b\L{e<=1}\b", + " book dog cot desk ", words="cat dog".split()), ["dog", "cot"]) + self.assertEqual(regex.findall(r"(?r)\b\L{e<=1}\b", + " book cot dog desk ", words="cat dog".split()), ["dog ", "cot"]) + self.assertEqual(regex.findall(r"(?er)\b\L{e<=1}\b", + " book cot dog desk ", words="cat dog".split()), ["dog", "cot"]) + self.assertEqual(regex.findall(r"(?r)\b\L{e<=1}\b", + " book dog cot desk ", words="cat dog".split()), ["cot", "dog"]) + self.assertEqual(regex.findall(br"\b\L{e<=1}\b", + b" book cot dog desk ", words=b"cat dog".split()), [b"cot", b"dog"]) + self.assertEqual(regex.findall(br"\b\L{e<=1}\b", + b" book dog cot desk ", words=b"cat dog".split()), [b" dog", b"cot"]) + self.assertEqual(regex.findall(br"(?e)\b\L{e<=1}\b", + b" book dog cot desk ", words=b"cat dog".split()), [b"dog", b"cot"]) + self.assertEqual(regex.findall(br"(?r)\b\L{e<=1}\b", + b" book cot dog desk ", words=b"cat dog".split()), [b"dog ", b"cot"]) + self.assertEqual(regex.findall(br"(?er)\b\L{e<=1}\b", + b" book cot dog desk ", words=b"cat dog".split()), [b"dog", b"cot"]) + self.assertEqual(regex.findall(br"(?r)\b\L{e<=1}\b", + b" book dog cot desk ", words=b"cat dog".split()), [b"cot", b"dog"]) + + self.assertEqual(regex.search(r"(\w+) (\1{e<=1})", "foo fou").groups(), + ("foo", "fou")) + self.assertEqual(regex.search(r"(?r)(\2{e<=1}) (\w+)", + "foo fou").groups(), ("foo", "fou")) + self.assertEqual(regex.search(br"(\w+) (\1{e<=1})", + b"foo fou").groups(), (b"foo", b"fou")) + + self.assertEqual(regex.findall(r"(?:(?:QR)+){e}", "abcde"), ["abcde", + ""]) + self.assertEqual(regex.findall(r"(?:Q+){e}", "abc"), ["abc", ""]) + + # Hg issue 41: = for fuzzy matches + self.assertEqual(regex.match(r"(?:service detection){0[^()]+)|(?R))*\)", "(ab(cd)ef)")[ + : ], ("(ab(cd)ef)", "ef")) + self.assertEqual(regex.search(r"\(((?>[^()]+)|(?R))*\)", + "(ab(cd)ef)").captures(1), ["ab", "cd", "(cd)", "ef"]) + + self.assertEqual(regex.search(r"(?r)\(((?R)|(?>[^()]+))*\)", + "(ab(cd)ef)")[ : ], ("(ab(cd)ef)", "ab")) + self.assertEqual(regex.search(r"(?r)\(((?R)|(?>[^()]+))*\)", + "(ab(cd)ef)").captures(1), ["ef", "cd", "(cd)", "ab"]) + + self.assertEqual(regex.search(r"\(([^()]+|(?R))*\)", + "some text (a(b(c)d)e) more text")[ : ], ("(a(b(c)d)e)", "e")) + + self.assertEqual(regex.search(r"(?r)\(((?R)|[^()]+)*\)", + "some text (a(b(c)d)e) more text")[ : ], ("(a(b(c)d)e)", "a")) + + self.assertEqual(regex.search(r"(foo(\(((?:(?>[^()]+)|(?2))*)\)))", + "foo(bar(baz)+baz(bop))")[ : ], ("foo(bar(baz)+baz(bop))", + "foo(bar(baz)+baz(bop))", "(bar(baz)+baz(bop))", + "bar(baz)+baz(bop)")) + + self.assertEqual(regex.search(r"(?r)(foo(\(((?:(?2)|(?>[^()]+))*)\)))", + "foo(bar(baz)+baz(bop))")[ : ], ("foo(bar(baz)+baz(bop))", + "foo(bar(baz)+baz(bop))", "(bar(baz)+baz(bop))", + "bar(baz)+baz(bop)")) + + rgx = regex.compile(r"""^\s*(<\s*([a-zA-Z:]+)(?:\s*[a-zA-Z:]*\s*=\s*(?:'[^']*'|"[^"]*"))*\s*(/\s*)?>(?:[^<>]*|(?1))*(?(3)|<\s*/\s*\2\s*>))\s*$""") + self.assertEqual(bool(rgx.search('')), True) + self.assertEqual(bool(rgx.search('')), False) + self.assertEqual(bool(rgx.search('')), True) + self.assertEqual(bool(rgx.search('')), False) + self.assertEqual(bool(rgx.search('')), False) + + self.assertEqual(bool(rgx.search('')), False) + self.assertEqual(bool(rgx.search('')), True) + self.assertEqual(bool(rgx.search('< fooo / >')), True) + # The next regex should and does match. Perl 5.14 agrees. + #self.assertEqual(bool(rgx.search('foo')), False) + self.assertEqual(bool(rgx.search('foo')), False) + + self.assertEqual(bool(rgx.search('foo')), True) + self.assertEqual(bool(rgx.search('foo')), True) + self.assertEqual(bool(rgx.search('')), True) + + def test_copy(self): + # PatternObjects are immutable, therefore there's no need to clone them. + r = regex.compile("a") + self.assertTrue(copy.copy(r) is r) + self.assertTrue(copy.deepcopy(r) is r) + + # MatchObjects are normally mutable because the target string can be + # detached. However, after the target string has been detached, a + # MatchObject becomes immutable, so there's no need to clone it. + m = r.match("a") + self.assertTrue(copy.copy(m) is not m) + self.assertTrue(copy.deepcopy(m) is not m) + + self.assertTrue(m.string is not None) + m2 = copy.copy(m) + m2.detach_string() + self.assertTrue(m.string is not None) + self.assertTrue(m2.string is None) + + # The following behaviour matches that of the re module. + it = regex.finditer(".", "ab") + it2 = copy.copy(it) + self.assertEqual(next(it).group(), "a") + self.assertEqual(next(it2).group(), "b") + + # The following behaviour matches that of the re module. + it = regex.finditer(".", "ab") + it2 = copy.deepcopy(it) + self.assertEqual(next(it).group(), "a") + self.assertEqual(next(it2).group(), "b") + + # The following behaviour is designed to match that of copying 'finditer'. + it = regex.splititer(" ", "a b") + it2 = copy.copy(it) + self.assertEqual(next(it), "a") + self.assertEqual(next(it2), "b") + + # The following behaviour is designed to match that of copying 'finditer'. + it = regex.splititer(" ", "a b") + it2 = copy.deepcopy(it) + self.assertEqual(next(it), "a") + self.assertEqual(next(it2), "b") + + def test_format(self): + self.assertEqual(regex.subf(r"(\w+) (\w+)", "{0} => {2} {1}", + "foo bar"), "foo bar => bar foo") + self.assertEqual(regex.subf(r"(?\w+) (?\w+)", + "{word2} {word1}", "foo bar"), "bar foo") + + self.assertEqual(regex.subfn(r"(\w+) (\w+)", "{0} => {2} {1}", + "foo bar"), ("foo bar => bar foo", 1)) + self.assertEqual(regex.subfn(r"(?\w+) (?\w+)", + "{word2} {word1}", "foo bar"), ("bar foo", 1)) + + self.assertEqual(regex.match(r"(\w+) (\w+)", + "foo bar").expandf("{0} => {2} {1}"), "foo bar => bar foo") + + def test_fullmatch(self): + self.assertEqual(bool(regex.fullmatch(r"abc", "abc")), True) + self.assertEqual(bool(regex.fullmatch(r"abc", "abcx")), False) + self.assertEqual(bool(regex.fullmatch(r"abc", "abcx", endpos=3)), True) + + self.assertEqual(bool(regex.fullmatch(r"abc", "xabc", pos=1)), True) + self.assertEqual(bool(regex.fullmatch(r"abc", "xabcy", pos=1)), False) + self.assertEqual(bool(regex.fullmatch(r"abc", "xabcy", pos=1, + endpos=4)), True) + + self.assertEqual(bool(regex.fullmatch(r"(?r)abc", "abc")), True) + self.assertEqual(bool(regex.fullmatch(r"(?r)abc", "abcx")), False) + self.assertEqual(bool(regex.fullmatch(r"(?r)abc", "abcx", endpos=3)), + True) + + self.assertEqual(bool(regex.fullmatch(r"(?r)abc", "xabc", pos=1)), + True) + self.assertEqual(bool(regex.fullmatch(r"(?r)abc", "xabcy", pos=1)), + False) + self.assertEqual(bool(regex.fullmatch(r"(?r)abc", "xabcy", pos=1, + endpos=4)), True) + + def test_issue_18468(self): + self.assertTypedEqual(regex.sub('y', 'a', 'xyz'), 'xaz') + self.assertTypedEqual(regex.sub('y', StrSubclass('a'), + StrSubclass('xyz')), 'xaz') + self.assertTypedEqual(regex.sub(b'y', b'a', b'xyz'), b'xaz') + self.assertTypedEqual(regex.sub(b'y', BytesSubclass(b'a'), + BytesSubclass(b'xyz')), b'xaz') + self.assertTypedEqual(regex.sub(b'y', bytearray(b'a'), + bytearray(b'xyz')), b'xaz') + self.assertTypedEqual(regex.sub(b'y', memoryview(b'a'), + memoryview(b'xyz')), b'xaz') + + for string in ":a:b::c", StrSubclass(":a:b::c"): + self.assertTypedEqual(regex.split(":", string), ['', 'a', 'b', '', + 'c']) + if sys.version_info >= (3, 7, 0): + self.assertTypedEqual(regex.split(":*", string), ['', '', 'a', + '', 'b', '', 'c', '']) + self.assertTypedEqual(regex.split("(:*)", string), ['', ':', + '', '', 'a', ':', '', '', 'b', '::', '', '', 'c', '', '']) + else: + self.assertTypedEqual(regex.split(":*", string), ['', 'a', 'b', + 'c']) + self.assertTypedEqual(regex.split("(:*)", string), ['', ':', + 'a', ':', 'b', '::', 'c']) + + for string in (b":a:b::c", BytesSubclass(b":a:b::c"), + bytearray(b":a:b::c"), memoryview(b":a:b::c")): + self.assertTypedEqual(regex.split(b":", string), [b'', b'a', b'b', + b'', b'c']) + if sys.version_info >= (3, 7, 0): + self.assertTypedEqual(regex.split(b":*", string), [b'', b'', + b'a', b'', b'b', b'', b'c', b'']) + self.assertTypedEqual(regex.split(b"(:*)", string), [b'', b':', + b'', b'', b'a', b':', b'', b'', b'b', b'::', b'', b'', b'c', + b'', b'']) + else: + self.assertTypedEqual(regex.split(b":*", string), [b'', b'a', + b'b', b'c']) + self.assertTypedEqual(regex.split(b"(:*)", string), [b'', b':', + b'a', b':', b'b', b'::', b'c']) + + for string in "a:b::c:::d", StrSubclass("a:b::c:::d"): + self.assertTypedEqual(regex.findall(":+", string), [":", "::", + ":::"]) + self.assertTypedEqual(regex.findall("(:+)", string), [":", "::", + ":::"]) + self.assertTypedEqual(regex.findall("(:)(:*)", string), [(":", ""), + (":", ":"), (":", "::")]) + + for string in (b"a:b::c:::d", BytesSubclass(b"a:b::c:::d"), + bytearray(b"a:b::c:::d"), memoryview(b"a:b::c:::d")): + self.assertTypedEqual(regex.findall(b":+", string), [b":", b"::", + b":::"]) + self.assertTypedEqual(regex.findall(b"(:+)", string), [b":", b"::", + b":::"]) + self.assertTypedEqual(regex.findall(b"(:)(:*)", string), [(b":", + b""), (b":", b":"), (b":", b"::")]) + + for string in 'a', StrSubclass('a'): + self.assertEqual(regex.match('a', string).groups(), ()) + self.assertEqual(regex.match('(a)', string).groups(), ('a',)) + self.assertEqual(regex.match('(a)', string).group(0), 'a') + self.assertEqual(regex.match('(a)', string).group(1), 'a') + self.assertEqual(regex.match('(a)', string).group(1, 1), ('a', + 'a')) + + for string in (b'a', BytesSubclass(b'a'), bytearray(b'a'), + memoryview(b'a')): + self.assertEqual(regex.match(b'a', string).groups(), ()) + self.assertEqual(regex.match(b'(a)', string).groups(), (b'a',)) + self.assertEqual(regex.match(b'(a)', string).group(0), b'a') + self.assertEqual(regex.match(b'(a)', string).group(1), b'a') + self.assertEqual(regex.match(b'(a)', string).group(1, 1), (b'a', + b'a')) + + def test_partial(self): + self.assertEqual(regex.match('ab', 'a', partial=True).partial, True) + self.assertEqual(regex.match('ab', 'a', partial=True).span(), (0, 1)) + self.assertEqual(regex.match(r'cats', 'cat', partial=True).partial, + True) + self.assertEqual(regex.match(r'cats', 'cat', partial=True).span(), (0, + 3)) + self.assertEqual(regex.match(r'cats', 'catch', partial=True), None) + self.assertEqual(regex.match(r'abc\w{3}', 'abcdef', + partial=True).partial, False) + self.assertEqual(regex.match(r'abc\w{3}', 'abcdef', + partial=True).span(), (0, 6)) + self.assertEqual(regex.match(r'abc\w{3}', 'abcde', + partial=True).partial, True) + self.assertEqual(regex.match(r'abc\w{3}', 'abcde', + partial=True).span(), (0, 5)) + + self.assertEqual(regex.match(r'\d{4}$', '1234', partial=True).partial, + False) + + self.assertEqual(regex.match(r'\L', 'post', partial=True, + words=['post']).partial, False) + self.assertEqual(regex.match(r'\L', 'post', partial=True, + words=['post']).span(), (0, 4)) + self.assertEqual(regex.match(r'\L', 'pos', partial=True, + words=['post']).partial, True) + self.assertEqual(regex.match(r'\L', 'pos', partial=True, + words=['post']).span(), (0, 3)) + + self.assertEqual(regex.match(r'(?fi)\L', 'POST', partial=True, + words=['po\uFB06']).partial, False) + self.assertEqual(regex.match(r'(?fi)\L', 'POST', partial=True, + words=['po\uFB06']).span(), (0, 4)) + self.assertEqual(regex.match(r'(?fi)\L', 'POS', partial=True, + words=['po\uFB06']).partial, True) + self.assertEqual(regex.match(r'(?fi)\L', 'POS', partial=True, + words=['po\uFB06']).span(), (0, 3)) + self.assertEqual(regex.match(r'(?fi)\L', 'po\uFB06', + partial=True, words=['POS']), None) + + self.assertEqual(regex.match(r'[a-z]*4R$', 'a', partial=True).span(), + (0, 1)) + self.assertEqual(regex.match(r'[a-z]*4R$', 'ab', partial=True).span(), + (0, 2)) + self.assertEqual(regex.match(r'[a-z]*4R$', 'ab4', partial=True).span(), + (0, 3)) + self.assertEqual(regex.match(r'[a-z]*4R$', 'a4', partial=True).span(), + (0, 2)) + self.assertEqual(regex.match(r'[a-z]*4R$', 'a4R', partial=True).span(), + (0, 3)) + self.assertEqual(regex.match(r'[a-z]*4R$', '4a', partial=True), None) + self.assertEqual(regex.match(r'[a-z]*4R$', 'a44', partial=True), None) + + def test_hg_bugs(self): + # Hg issue 28: regex.compile("(?>b)") causes "TypeError: 'Character' + # object is not subscriptable" + self.assertEqual(bool(regex.compile("(?>b)", flags=regex.V1)), True) + + # Hg issue 29: regex.compile("^((?>\w+)|(?>\s+))*$") causes + # "TypeError: 'GreedyRepeat' object is not iterable" + self.assertEqual(bool(regex.compile(r"^((?>\w+)|(?>\s+))*$", + flags=regex.V1)), True) + + # Hg issue 31: atomic and normal groups in recursive patterns + self.assertEqual(regex.findall(r"\((?:(?>[^()]+)|(?R))*\)", + "a(bcd(e)f)g(h)"), ['(bcd(e)f)', '(h)']) + self.assertEqual(regex.findall(r"\((?:(?:[^()]+)|(?R))*\)", + "a(bcd(e)f)g(h)"), ['(bcd(e)f)', '(h)']) + self.assertEqual(regex.findall(r"\((?:(?>[^()]+)|(?R))*\)", + "a(b(cd)e)f)g)h"), ['(b(cd)e)']) + self.assertEqual(regex.findall(r"\((?:(?>[^()]+)|(?R))*\)", + "a(bc(d(e)f)gh"), ['(d(e)f)']) + self.assertEqual(regex.findall(r"(?r)\((?:(?>[^()]+)|(?R))*\)", + "a(bc(d(e)f)gh"), ['(d(e)f)']) + self.assertEqual([m.group() for m in + regex.finditer(r"\((?:[^()]*+|(?0))*\)", "a(b(c(de)fg)h")], + ['(c(de)fg)']) + + # Hg issue 32: regex.search("a(bc)d", "abcd", regex.I|regex.V1) returns + # None + self.assertEqual(regex.search("a(bc)d", "abcd", regex.I | + regex.V1).group(0), "abcd") + + # Hg issue 33: regex.search("([\da-f:]+)$", "E", regex.I|regex.V1) + # returns None + self.assertEqual(regex.search(r"([\da-f:]+)$", "E", regex.I | + regex.V1).group(0), "E") + self.assertEqual(regex.search(r"([\da-f:]+)$", "e", regex.I | + regex.V1).group(0), "e") + + # Hg issue 34: regex.search("^(?=ab(de))(abd)(e)", "abde").groups() + # returns (None, 'abd', 'e') instead of ('de', 'abd', 'e') + self.assertEqual(regex.search("^(?=ab(de))(abd)(e)", "abde").groups(), + ('de', 'abd', 'e')) + + # Hg issue 35: regex.compile("\ ", regex.X) causes "_regex_core.error: + # bad escape" + self.assertEqual(bool(regex.match(r"\ ", " ", flags=regex.X)), True) + + # Hg issue 36: regex.search("^(a|)\1{2}b", "b") returns None + self.assertEqual(regex.search(r"^(a|)\1{2}b", "b").group(0, 1), ('b', + '')) + + # Hg issue 37: regex.search("^(a){0,0}", "abc").group(0,1) returns + # ('a', 'a') instead of ('', None) + self.assertEqual(regex.search("^(a){0,0}", "abc").group(0, 1), ('', + None)) + + # Hg issue 38: regex.search("(?>.*/)b", "a/b") returns None + self.assertEqual(regex.search("(?>.*/)b", "a/b").group(0), "a/b") + + # Hg issue 39: regex.search("((?i)blah)\\s+\\1", "blah BLAH") doesn't + # return None + # Changed to positional flags in regex 2023.12.23. + self.assertEqual(regex.search(r"((?i)blah)\s+\1", "blah BLAH"), None) + + # Hg issue 40: regex.search("(\()?[^()]+(?(1)\)|)", "(abcd").group(0) + # returns "bcd" instead of "abcd" + self.assertEqual(regex.search(r"(\()?[^()]+(?(1)\)|)", + "(abcd").group(0), "abcd") + + # Hg issue 42: regex.search("(a*)*", "a", flags=regex.V1).span(1) + # returns (0, 1) instead of (1, 1) + self.assertEqual(regex.search("(a*)*", "a").span(1), (1, 1)) + self.assertEqual(regex.search("(a*)*", "aa").span(1), (2, 2)) + self.assertEqual(regex.search("(a*)*", "aaa").span(1), (3, 3)) + + # Hg issue 43: regex.compile("a(?#xxx)*") causes "_regex_core.error: + # nothing to repeat" + self.assertEqual(regex.search("a(?#xxx)*", "aaa").group(), "aaa") + + # Hg issue 44: regex.compile("(?=abc){3}abc") causes + # "_regex_core.error: nothing to repeat" + self.assertEqual(regex.search("(?=abc){3}abc", "abcabcabc").span(), (0, + 3)) + + # Hg issue 45: regex.compile("^(?:a(?:(?:))+)+") causes + # "_regex_core.error: nothing to repeat" + self.assertEqual(regex.search("^(?:a(?:(?:))+)+", "a").span(), (0, 1)) + self.assertEqual(regex.search("^(?:a(?:(?:))+)+", "aa").span(), (0, 2)) + + # Hg issue 46: regex.compile("a(?x: b c )d") causes + # "_regex_core.error: missing )" + self.assertEqual(regex.search("a(?x: b c )d", "abcd").group(0), "abcd") + + # Hg issue 47: regex.compile("a#comment\n*", flags=regex.X) causes + # "_regex_core.error: nothing to repeat" + self.assertEqual(regex.search("a#comment\n*", "aaa", + flags=regex.X).group(0), "aaa") + + # Hg issue 48: regex.search("(a(?(1)\\1)){4}", "a"*10, + # flags=regex.V1).group(0,1) returns ('aaaaa', 'a') instead of ('aaaaaaaaaa', 'aaaa') + self.assertEqual(regex.search(r"(?V1)(a(?(1)\1)){1}", + "aaaaaaaaaa").span(0, 1), ((0, 1), (0, 1))) + self.assertEqual(regex.search(r"(?V1)(a(?(1)\1)){2}", + "aaaaaaaaaa").span(0, 1), ((0, 3), (1, 3))) + self.assertEqual(regex.search(r"(?V1)(a(?(1)\1)){3}", + "aaaaaaaaaa").span(0, 1), ((0, 6), (3, 6))) + self.assertEqual(regex.search(r"(?V1)(a(?(1)\1)){4}", + "aaaaaaaaaa").span(0, 1), ((0, 10), (6, 10))) + + # Hg issue 49: regex.search("(a)(?<=b(?1))", "baz", regex.V1) returns + # None incorrectly + self.assertEqual(regex.search("(?V1)(a)(?<=b(?1))", "baz").group(0), + "a") + + # Hg issue 50: not all keywords are found by named list with + # overlapping keywords when full Unicode casefolding is required + self.assertEqual(regex.findall(r'(?fi)\L', + 'POST, Post, post, po\u017Ft, po\uFB06, and po\uFB05', + keywords=['post','pos']), ['POST', 'Post', 'post', 'po\u017Ft', + 'po\uFB06', 'po\uFB05']) + self.assertEqual(regex.findall(r'(?fi)pos|post', + 'POST, Post, post, po\u017Ft, po\uFB06, and po\uFB05'), ['POS', + 'Pos', 'pos', 'po\u017F', 'po\uFB06', 'po\uFB05']) + self.assertEqual(regex.findall(r'(?fi)post|pos', + 'POST, Post, post, po\u017Ft, po\uFB06, and po\uFB05'), ['POST', + 'Post', 'post', 'po\u017Ft', 'po\uFB06', 'po\uFB05']) + self.assertEqual(regex.findall(r'(?fi)post|another', + 'POST, Post, post, po\u017Ft, po\uFB06, and po\uFB05'), ['POST', + 'Post', 'post', 'po\u017Ft', 'po\uFB06', 'po\uFB05']) + + # Hg issue 51: regex.search("((a)(?1)|(?2))", "a", flags=regex.V1) + # returns None incorrectly + self.assertEqual(regex.search("(?V1)((a)(?1)|(?2))", "a").group(0, 1, + 2), ('a', 'a', None)) + + # Hg issue 52: regex.search("(\\1xx|){6}", "xx", + # flags=regex.V1).span(0,1) returns incorrect value + self.assertEqual(regex.search(r"(?V1)(\1xx|){6}", "xx").span(0, 1), + ((0, 2), (2, 2))) + + # Hg issue 53: regex.search("(a|)+", "a") causes MemoryError + self.assertEqual(regex.search("(a|)+", "a").group(0, 1), ("a", "")) + + # Hg issue 54: regex.search("(a|)*\\d", "a"*80) causes MemoryError + self.assertEqual(regex.search(r"(a|)*\d", "a" * 80), None) + + # Hg issue 55: regex.search("^(?:a?b?)*$", "ac") take a very long time. + self.assertEqual(regex.search("^(?:a?b?)*$", "ac"), None) + + # Hg issue 58: bad named character escape sequences like "\\N{1}" + # treats as "N" + self.assertRaisesRegex(regex.error, self.UNDEF_CHAR_NAME, lambda: + regex.compile("\\N{1}")) + + # Hg issue 59: regex.search("\\Z", "a\na\n") returns None incorrectly + self.assertEqual(regex.search("\\Z", "a\na\n").span(0), (4, 4)) + + # Hg issue 60: regex.search("(q1|.)*(q2|.)*(x(a|bc)*y){2,}", "xayxay") + # returns None incorrectly + self.assertEqual(regex.search("(q1|.)*(q2|.)*(x(a|bc)*y){2,}", + "xayxay").group(0), "xayxay") + + # Hg issue 61: regex.search("[^a]", "A", regex.I).group(0) returns '' + # incorrectly + self.assertEqual(regex.search("(?i)[^a]", "A"), None) + + # Hg issue 63: regex.search("[[:ascii:]]", "\N{KELVIN SIGN}", + # flags=regex.I|regex.V1) doesn't return None + self.assertEqual(regex.search("(?i)[[:ascii:]]", "\N{KELVIN SIGN}"), + None) + + # Hg issue 66: regex.search("((a|b(?1)c){3,5})", "baaaaca", + # flags=regex.V1).groups() returns ('baaaac', 'baaaac') instead of ('aaaa', 'a') + self.assertEqual(regex.search("((a|b(?1)c){3,5})", "baaaaca").group(0, + 1, 2), ('aaaa', 'aaaa', 'a')) + + # Hg issue 71: non-greedy quantifier in lookbehind + self.assertEqual(regex.findall(r"(?<=:\S+ )\w+", ":9 abc :10 def"), + ['abc', 'def']) + self.assertEqual(regex.findall(r"(?<=:\S* )\w+", ":9 abc :10 def"), + ['abc', 'def']) + self.assertEqual(regex.findall(r"(?<=:\S+? )\w+", ":9 abc :10 def"), + ['abc', 'def']) + self.assertEqual(regex.findall(r"(?<=:\S*? )\w+", ":9 abc :10 def"), + ['abc', 'def']) + + # Hg issue 73: conditional patterns + self.assertEqual(regex.search(r"(?:fe)?male", "female").group(), + "female") + self.assertEqual([m.group() for m in + regex.finditer(r"(fe)?male: h(?(1)(er)|(is)) (\w+)", + "female: her dog; male: his cat. asdsasda")], ['female: her dog', + 'male: his cat']) + + # Hg issue 78: "Captures" doesn't work for recursive calls + self.assertEqual(regex.search(r'(?\((?:[^()]++|(?&rec))*\))', + 'aaa(((1+0)+1)+1)bbb').captures('rec'), ['(1+0)', '((1+0)+1)', + '(((1+0)+1)+1)']) + + # Hg issue 80: Escape characters throws an exception + self.assertRaisesRegex(regex.error, self.BAD_ESCAPE, lambda: + regex.sub('x', '\\', 'x'), ) + + # Hg issue 82: error range does not work + fz = "(CAGCCTCCCATTTCAGAATATACATCC){1a(?b))', "ab").spans("x"), [(1, + 2), (0, 2)]) + + # Hg issue 91: match.expand is extremely slow + # Check that the replacement cache works. + self.assertEqual(regex.sub(r'(-)', lambda m: m.expand(r'x'), 'a-b-c'), + 'axbxc') + + # Hg issue 94: Python crashes when executing regex updates + # pattern.findall + rx = regex.compile(r'\bt(est){i<2}', flags=regex.V1) + self.assertEqual(rx.search("Some text"), None) + self.assertEqual(rx.findall("Some text"), []) + + # Hg issue 95: 'pos' for regex.error + self.assertRaisesRegex(regex.error, self.MULTIPLE_REPEAT, lambda: + regex.compile(r'.???')) + + # Hg issue 97: behaviour of regex.escape's special_only is wrong + # + # Hg issue 244: Make `special_only=True` the default in + # `regex.escape()` + self.assertEqual(regex.escape('foo!?', special_only=False), 'foo\\!\\?') + self.assertEqual(regex.escape('foo!?', special_only=True), 'foo!\\?') + self.assertEqual(regex.escape('foo!?'), 'foo!\\?') + + self.assertEqual(regex.escape(b'foo!?', special_only=False), b'foo\\!\\?') + self.assertEqual(regex.escape(b'foo!?', special_only=True), + b'foo!\\?') + self.assertEqual(regex.escape(b'foo!?'), b'foo!\\?') + + # Hg issue 100: strange results from regex.search + self.assertEqual(regex.search('^([^z]*(?:WWWi|W))?$', + 'WWWi').groups(), ('WWWi', )) + self.assertEqual(regex.search('^([^z]*(?:WWWi|w))?$', + 'WWWi').groups(), ('WWWi', )) + self.assertEqual(regex.search('^([^z]*?(?:WWWi|W))?$', + 'WWWi').groups(), ('WWWi', )) + + # Hg issue 101: findall() broken (seems like memory corruption) + pat = regex.compile(r'xxx', flags=regex.FULLCASE | regex.UNICODE) + self.assertEqual([x.group() for x in pat.finditer('yxxx')], ['xxx']) + self.assertEqual(pat.findall('yxxx'), ['xxx']) + + raw = 'yxxx' + self.assertEqual([x.group() for x in pat.finditer(raw)], ['xxx']) + self.assertEqual(pat.findall(raw), ['xxx']) + + pat = regex.compile(r'xxx', flags=regex.FULLCASE | regex.IGNORECASE | + regex.UNICODE) + self.assertEqual([x.group() for x in pat.finditer('yxxx')], ['xxx']) + self.assertEqual(pat.findall('yxxx'), ['xxx']) + + raw = 'yxxx' + self.assertEqual([x.group() for x in pat.finditer(raw)], ['xxx']) + self.assertEqual(pat.findall(raw), ['xxx']) + + # Hg issue 106: * operator not working correctly with sub() + if sys.version_info >= (3, 7, 0): + self.assertEqual(regex.sub('(?V0).*', 'x', 'test'), 'xx') + else: + self.assertEqual(regex.sub('(?V0).*', 'x', 'test'), 'x') + self.assertEqual(regex.sub('(?V1).*', 'x', 'test'), 'xx') + + if sys.version_info >= (3, 7, 0): + self.assertEqual(regex.sub('(?V0).*?', '|', 'test'), '|||||||||') + else: + self.assertEqual(regex.sub('(?V0).*?', '|', 'test'), '|t|e|s|t|') + self.assertEqual(regex.sub('(?V1).*?', '|', 'test'), '|||||||||') + + # Hg issue 112: re: OK, but regex: SystemError + self.assertEqual(regex.sub(r'^(@)\n(?!.*?@)(.*)', + r'\1\n==========\n\2', '@\n', flags=regex.DOTALL), '@\n==========\n') + + # Hg issue 109: Edit distance of fuzzy match + self.assertEqual(regex.match(r'(?:cats|cat){e<=1}', + 'caz').fuzzy_counts, (1, 0, 0)) + self.assertEqual(regex.match(r'(?e)(?:cats|cat){e<=1}', + 'caz').fuzzy_counts, (1, 0, 0)) + self.assertEqual(regex.match(r'(?b)(?:cats|cat){e<=1}', + 'caz').fuzzy_counts, (1, 0, 0)) + + self.assertEqual(regex.match(r'(?:cat){e<=1}', 'caz').fuzzy_counts, + (1, 0, 0)) + self.assertEqual(regex.match(r'(?e)(?:cat){e<=1}', + 'caz').fuzzy_counts, (1, 0, 0)) + self.assertEqual(regex.match(r'(?b)(?:cat){e<=1}', + 'caz').fuzzy_counts, (1, 0, 0)) + + self.assertEqual(regex.match(r'(?:cats){e<=2}', 'c ats').fuzzy_counts, + (1, 1, 0)) + self.assertEqual(regex.match(r'(?e)(?:cats){e<=2}', + 'c ats').fuzzy_counts, (0, 1, 0)) + self.assertEqual(regex.match(r'(?b)(?:cats){e<=2}', + 'c ats').fuzzy_counts, (0, 1, 0)) + + self.assertEqual(regex.match(r'(?:cats){e<=2}', + 'c a ts').fuzzy_counts, (0, 2, 0)) + self.assertEqual(regex.match(r'(?e)(?:cats){e<=2}', + 'c a ts').fuzzy_counts, (0, 2, 0)) + self.assertEqual(regex.match(r'(?b)(?:cats){e<=2}', + 'c a ts').fuzzy_counts, (0, 2, 0)) + + self.assertEqual(regex.match(r'(?:cats){e<=1}', 'c ats').fuzzy_counts, + (0, 1, 0)) + self.assertEqual(regex.match(r'(?e)(?:cats){e<=1}', + 'c ats').fuzzy_counts, (0, 1, 0)) + self.assertEqual(regex.match(r'(?b)(?:cats){e<=1}', + 'c ats').fuzzy_counts, (0, 1, 0)) + + # Hg issue 115: Infinite loop when processing backreferences + self.assertEqual(regex.findall(r'\bof ([a-z]+) of \1\b', + 'To make use of one of these modules'), []) + + # Hg issue 125: Reference to entire match (\g<0>) in + # Pattern.sub() doesn't work as of 2014.09.22 release. + self.assertEqual(regex.sub(r'x', r'\g<0>', 'x'), 'x') + + # Unreported issue: no such builtin as 'ascii' in Python 2. + self.assertEqual(bool(regex.match(r'a', 'a', regex.DEBUG)), True) + + # Hg issue 131: nested sets behaviour + self.assertEqual(regex.findall(r'(?V1)[[b-e]--cd]', 'abcdef'), ['b', + 'e']) + self.assertEqual(regex.findall(r'(?V1)[b-e--cd]', 'abcdef'), ['b', + 'e']) + self.assertEqual(regex.findall(r'(?V1)[[bcde]--cd]', 'abcdef'), ['b', + 'e']) + self.assertEqual(regex.findall(r'(?V1)[bcde--cd]', 'abcdef'), ['b', + 'e']) + + # Hg issue 132: index out of range on null property \p{} + self.assertRaisesRegex(regex.error, '^unknown property at position 4$', + lambda: regex.compile(r'\p{}')) + + # Issue 23692. + self.assertEqual(regex.match('(?:()|(?(1)()|z)){2}(?(2)a|z)', + 'a').group(0, 1, 2), ('a', '', '')) + self.assertEqual(regex.match('(?:()|(?(1)()|z)){0,2}(?(2)a|z)', + 'a').group(0, 1, 2), ('a', '', '')) + + # Hg issue 137: Posix character class :punct: does not seem to be + # supported. + + # Posix compatibility as recommended here: + # http://www.unicode.org/reports/tr18/#Compatibility_Properties + + # Posix in Unicode. + chars = ''.join(chr(c) for c in range(0x10000)) + + self.assertEqual(ascii(''.join(regex.findall(r'''[[:alnum:]]+''', + chars))), ascii(''.join(regex.findall(r'''[\p{Alpha}\p{PosixDigit}]+''', + chars)))) + self.assertEqual(ascii(''.join(regex.findall(r'''[[:alpha:]]+''', + chars))), ascii(''.join(regex.findall(r'''\p{Alpha}+''', + chars)))) + self.assertEqual(ascii(''.join(regex.findall(r'''[[:ascii:]]+''', + chars))), ascii(''.join(regex.findall(r'''[\p{InBasicLatin}]+''', + chars)))) + self.assertEqual(ascii(''.join(regex.findall(r'''[[:blank:]]+''', + chars))), ascii(''.join(regex.findall(r'''[\p{gc=Space_Separator}\t]+''', + chars)))) + self.assertEqual(ascii(''.join(regex.findall(r'''[[:cntrl:]]+''', + chars))), ascii(''.join(regex.findall(r'''\p{gc=Control}+''', chars)))) + self.assertEqual(ascii(''.join(regex.findall(r'''[[:digit:]]+''', + chars))), ascii(''.join(regex.findall(r'''[0-9]+''', chars)))) + self.assertEqual(ascii(''.join(regex.findall(r'''[[:graph:]]+''', + chars))), ascii(''.join(regex.findall(r'''[^\p{Space}\p{gc=Control}\p{gc=Surrogate}\p{gc=Unassigned}]+''', + chars)))) + self.assertEqual(ascii(''.join(regex.findall(r'''[[:lower:]]+''', + chars))), ascii(''.join(regex.findall(r'''\p{Lower}+''', + chars)))) + self.assertEqual(ascii(''.join(regex.findall(r'''[[:print:]]+''', + chars))), ascii(''.join(regex.findall(r'''(?V1)[\p{Graph}\p{Blank}--\p{Cntrl}]+''', chars)))) + self.assertEqual(ascii(''.join(regex.findall(r'''[[:punct:]]+''', + chars))), + ascii(''.join(regex.findall(r'''(?V1)[\p{gc=Punctuation}\p{gc=Symbol}--\p{Alpha}]+''', + chars)))) + self.assertEqual(ascii(''.join(regex.findall(r'''[[:space:]]+''', + chars))), ascii(''.join(regex.findall(r'''\p{Whitespace}+''', + chars)))) + self.assertEqual(ascii(''.join(regex.findall(r'''[[:upper:]]+''', + chars))), ascii(''.join(regex.findall(r'''\p{Upper}+''', + chars)))) + self.assertEqual(ascii(''.join(regex.findall(r'''[[:word:]]+''', + chars))), ascii(''.join(regex.findall(r'''[\p{Alpha}\p{gc=Mark}\p{Digit}\p{gc=Connector_Punctuation}\p{Join_Control}]+''', + chars)))) + self.assertEqual(ascii(''.join(regex.findall(r'''[[:xdigit:]]+''', + chars))), ascii(''.join(regex.findall(r'''[0-9A-Fa-f]+''', + chars)))) + + # Posix in ASCII. + chars = bytes(range(0x100)) + + self.assertEqual(ascii(b''.join(regex.findall(br'''(?a)[[:alnum:]]+''', + chars))), ascii(b''.join(regex.findall(br'''(?a)[\p{Alpha}\p{PosixDigit}]+''', + chars)))) + self.assertEqual(ascii(b''.join(regex.findall(br'''(?a)[[:alpha:]]+''', + chars))), ascii(b''.join(regex.findall(br'''(?a)\p{Alpha}+''', chars)))) + self.assertEqual(ascii(b''.join(regex.findall(br'''(?a)[[:ascii:]]+''', + chars))), ascii(b''.join(regex.findall(br'''(?a)[\x00-\x7F]+''', chars)))) + self.assertEqual(ascii(b''.join(regex.findall(br'''(?a)[[:blank:]]+''', + chars))), ascii(b''.join(regex.findall(br'''(?a)[\p{gc=Space_Separator}\t]+''', + chars)))) + self.assertEqual(ascii(b''.join(regex.findall(br'''(?a)[[:cntrl:]]+''', + chars))), ascii(b''.join(regex.findall(br'''(?a)\p{gc=Control}+''', + chars)))) + self.assertEqual(ascii(b''.join(regex.findall(br'''(?a)[[:digit:]]+''', + chars))), ascii(b''.join(regex.findall(br'''(?a)[0-9]+''', chars)))) + self.assertEqual(ascii(b''.join(regex.findall(br'''(?a)[[:graph:]]+''', + chars))), ascii(b''.join(regex.findall(br'''(?a)[^\p{Space}\p{gc=Control}\p{gc=Surrogate}\p{gc=Unassigned}]+''', chars)))) + self.assertEqual(ascii(b''.join(regex.findall(br'''(?a)[[:lower:]]+''', + chars))), ascii(b''.join(regex.findall(br'''(?a)\p{Lower}+''', chars)))) + self.assertEqual(ascii(b''.join(regex.findall(br'''(?a)[[:print:]]+''', + chars))), ascii(b''.join(regex.findall(br'''(?aV1)[\p{Graph}\p{Blank}--\p{Cntrl}]+''', chars)))) + self.assertEqual(ascii(b''.join(regex.findall(br'''(?a)[[:punct:]]+''', + chars))), ascii(b''.join(regex.findall(br'''(?aV1)[\p{gc=Punctuation}\p{gc=Symbol}--\p{Alpha}]+''', + chars)))) + self.assertEqual(ascii(b''.join(regex.findall(br'''(?a)[[:space:]]+''', + chars))), ascii(b''.join(regex.findall(br'''(?a)\p{Whitespace}+''', chars)))) + self.assertEqual(ascii(b''.join(regex.findall(br'''(?a)[[:upper:]]+''', + chars))), ascii(b''.join(regex.findall(br'''(?a)\p{Upper}+''', chars)))) + self.assertEqual(ascii(b''.join(regex.findall(br'''(?a)[[:word:]]+''', + chars))), ascii(b''.join(regex.findall(br'''(?a)[\p{Alpha}\p{gc=Mark}\p{Digit}\p{gc=Connector_Punctuation}\p{Join_Control}]+''', chars)))) + self.assertEqual(ascii(b''.join(regex.findall(br'''(?a)[[:xdigit:]]+''', + chars))), ascii(b''.join(regex.findall(br'''(?a)[0-9A-Fa-f]+''', chars)))) + + # Hg issue 138: grapheme anchored search not working properly. + self.assertEqual(ascii(regex.search(r'\X$', 'ab\u2103').group()), + ascii('\u2103')) + + # Hg issue 139: Regular expression with multiple wildcards where first + # should match empty string does not always work. + self.assertEqual(regex.search("([^L]*)([^R]*R)", "LtR").groups(), ('', + 'LtR')) + + # Hg issue 140: Replace with REVERSE and groups has unexpected + # behavior. + self.assertEqual(regex.sub(r'(.)', r'x\1y', 'ab'), 'xayxby') + self.assertEqual(regex.sub(r'(?r)(.)', r'x\1y', 'ab'), 'xayxby') + self.assertEqual(regex.subf(r'(.)', 'x{1}y', 'ab'), 'xayxby') + self.assertEqual(regex.subf(r'(?r)(.)', 'x{1}y', 'ab'), 'xayxby') + + # Hg issue 141: Crash on a certain partial match. + self.assertEqual(regex.fullmatch('(a)*abc', 'ab', + partial=True).span(), (0, 2)) + self.assertEqual(regex.fullmatch('(a)*abc', 'ab', + partial=True).partial, True) + + # Hg issue 143: Partial matches have incorrect span if prefix is '.' + # wildcard. + self.assertEqual(regex.search('OXRG', 'OOGOX', partial=True).span(), + (3, 5)) + self.assertEqual(regex.search('.XRG', 'OOGOX', partial=True).span(), + (3, 5)) + self.assertEqual(regex.search('.{1,3}XRG', 'OOGOX', + partial=True).span(), (1, 5)) + + # Hg issue 144: Latest version problem with matching 'R|R'. + self.assertEqual(regex.match('R|R', 'R').span(), (0, 1)) + + # Hg issue 146: Forced-fail (?!) works improperly in conditional. + self.assertEqual(regex.match(r'(.)(?(1)(?!))', 'xy'), None) + + # Groups cleared after failure. + self.assertEqual(regex.findall(r'(y)?(\d)(?(1)\b\B)', 'ax1y2z3b'), + [('', '1'), ('', '2'), ('', '3')]) + self.assertEqual(regex.findall(r'(y)?+(\d)(?(1)\b\B)', 'ax1y2z3b'), + [('', '1'), ('', '2'), ('', '3')]) + + # Hg issue 147: Fuzzy match can return match points beyond buffer end. + self.assertEqual([m.span() for m in regex.finditer(r'(?i)(?:error){e}', + 'regex failure')], [(0, 5), (5, 10), (10, 13), (13, 13)]) + self.assertEqual([m.span() for m in + regex.finditer(r'(?fi)(?:error){e}', 'regex failure')], [(0, 5), (5, + 10), (10, 13), (13, 13)]) + + # Hg issue 150: Have an option for POSIX-compatible longest match of + # alternates. + self.assertEqual(regex.search(r'(?p)\d+(\w(\d*)?|[eE]([+-]\d+))', + '10b12')[0], '10b12') + self.assertEqual(regex.search(r'(?p)\d+(\w(\d*)?|[eE]([+-]\d+))', + '10E+12')[0], '10E+12') + + self.assertEqual(regex.search(r'(?p)(\w|ae|oe|ue|ss)', 'ae')[0], 'ae') + self.assertEqual(regex.search(r'(?p)one(self)?(selfsufficient)?', + 'oneselfsufficient')[0], 'oneselfsufficient') + + # Hg issue 151: Request: \K. + self.assertEqual(regex.search(r'(ab\Kcd)', 'abcd').group(0, 1), ('cd', + 'abcd')) + self.assertEqual(regex.findall(r'\w\w\K\w\w', 'abcdefgh'), ['cd', + 'gh']) + self.assertEqual(regex.findall(r'(\w\w\K\w\w)', 'abcdefgh'), ['abcd', + 'efgh']) + + self.assertEqual(regex.search(r'(?r)(ab\Kcd)', 'abcd').group(0, 1), + ('ab', 'abcd')) + self.assertEqual(regex.findall(r'(?r)\w\w\K\w\w', 'abcdefgh'), ['ef', + 'ab']) + self.assertEqual(regex.findall(r'(?r)(\w\w\K\w\w)', 'abcdefgh'), + ['efgh', 'abcd']) + + # Hg issue 152: Request: Request: (?(DEFINE)...). + self.assertEqual(regex.search(r'(?(DEFINE)(?\d+)(?\w+))(?&quant) (?&item)', + '5 elephants')[0], '5 elephants') + + self.assertEqual(regex.search(r'(?&routine)(?(DEFINE)(?.))', 'a').group('routine'), None) + self.assertEqual(regex.search(r'(?&routine)(?(DEFINE)(?.))', 'a').captures('routine'), ['a']) + + # Hg issue 153: Request: (*SKIP). + self.assertEqual(regex.search(r'12(*FAIL)|3', '123')[0], '3') + self.assertEqual(regex.search(r'(?r)12(*FAIL)|3', '123')[0], '3') + + self.assertEqual(regex.search(r'\d+(*PRUNE)\d', '123'), None) + self.assertEqual(regex.search(r'\d+(?=(*PRUNE))\d', '123')[0], '123') + self.assertEqual(regex.search(r'\d+(*PRUNE)bcd|[3d]', '123bcd')[0], + '123bcd') + self.assertEqual(regex.search(r'\d+(*PRUNE)bcd|[3d]', '123zzd')[0], + 'd') + self.assertEqual(regex.search(r'\d+?(*PRUNE)bcd|[3d]', '123bcd')[0], + '3bcd') + self.assertEqual(regex.search(r'\d+?(*PRUNE)bcd|[3d]', '123zzd')[0], + 'd') + self.assertEqual(regex.search(r'\d++(?<=3(*PRUNE))zzd|[4d]$', + '123zzd')[0], '123zzd') + self.assertEqual(regex.search(r'\d++(?<=3(*PRUNE))zzd|[4d]$', + '124zzd')[0], 'd') + self.assertEqual(regex.search(r'\d++(?<=(*PRUNE)3)zzd|[4d]$', + '124zzd')[0], 'd') + self.assertEqual(regex.search(r'\d++(?<=2(*PRUNE)3)zzd|[3d]$', + '124zzd')[0], 'd') + + self.assertEqual(regex.search(r'(?r)\d(*PRUNE)\d+', '123'), None) + self.assertEqual(regex.search(r'(?r)\d(?<=(*PRUNE))\d+', '123')[0], + '123') + self.assertEqual(regex.search(r'(?r)\d+(*PRUNE)bcd|[3d]', + '123bcd')[0], '123bcd') + self.assertEqual(regex.search(r'(?r)\d+(*PRUNE)bcd|[3d]', + '123zzd')[0], 'd') + self.assertEqual(regex.search(r'(?r)\d++(?<=3(*PRUNE))zzd|[4d]$', + '123zzd')[0], '123zzd') + self.assertEqual(regex.search(r'(?r)\d++(?<=3(*PRUNE))zzd|[4d]$', + '124zzd')[0], 'd') + self.assertEqual(regex.search(r'(?r)\d++(?<=(*PRUNE)3)zzd|[4d]$', + '124zzd')[0], 'd') + self.assertEqual(regex.search(r'(?r)\d++(?<=2(*PRUNE)3)zzd|[3d]$', + '124zzd')[0], 'd') + + self.assertEqual(regex.search(r'\d+(*SKIP)bcd|[3d]', '123bcd')[0], + '123bcd') + self.assertEqual(regex.search(r'\d+(*SKIP)bcd|[3d]', '123zzd')[0], + 'd') + self.assertEqual(regex.search(r'\d+?(*SKIP)bcd|[3d]', '123bcd')[0], + '3bcd') + self.assertEqual(regex.search(r'\d+?(*SKIP)bcd|[3d]', '123zzd')[0], + 'd') + self.assertEqual(regex.search(r'\d++(?<=3(*SKIP))zzd|[4d]$', + '123zzd')[0], '123zzd') + self.assertEqual(regex.search(r'\d++(?<=3(*SKIP))zzd|[4d]$', + '124zzd')[0], 'd') + self.assertEqual(regex.search(r'\d++(?<=(*SKIP)3)zzd|[4d]$', + '124zzd')[0], 'd') + self.assertEqual(regex.search(r'\d++(?<=2(*SKIP)3)zzd|[3d]$', + '124zzd')[0], 'd') + + self.assertEqual(regex.search(r'(?r)\d+(*SKIP)bcd|[3d]', '123bcd')[0], + '123bcd') + self.assertEqual(regex.search(r'(?r)\d+(*SKIP)bcd|[3d]', '123zzd')[0], + 'd') + self.assertEqual(regex.search(r'(?r)\d++(?<=3(*SKIP))zzd|[4d]$', + '123zzd')[0], '123zzd') + self.assertEqual(regex.search(r'(?r)\d++(?<=3(*SKIP))zzd|[4d]$', + '124zzd')[0], 'd') + self.assertEqual(regex.search(r'(?r)\d++(?<=(*SKIP)3)zzd|[4d]$', + '124zzd')[0], 'd') + self.assertEqual(regex.search(r'(?r)\d++(?<=2(*SKIP)3)zzd|[3d]$', + '124zzd')[0], 'd') + + # Hg issue 154: Segmentation fault 11 when working with an atomic group + text = """June 30, December 31, 2013 2012 +some words follow: +more words and numbers 1,234,567 9,876,542 +more words and numbers 1,234,567 9,876,542""" + self.assertEqual(len(regex.findall(r'(?2014|2013 ?2012)', text)), 1) + + # Hg issue 156: regression on atomic grouping + self.assertEqual(regex.match('1(?>2)', '12').span(), (0, 2)) + + # Hg issue 157: regression: segfault on complex lookaround + self.assertEqual(regex.match(r'(?V1w)(?=(?=[^A-Z]*+[A-Z])(?=[^a-z]*+[a-z]))(?=\D*+\d)(?=\p{Alphanumeric}*+\P{Alphanumeric})\A(?s:.){8,255}+\Z', + 'AAaa11!!')[0], 'AAaa11!!') + + # Hg issue 158: Group issue with (?(DEFINE)...) + TEST_REGEX = regex.compile(r'''(?smx) +(?(DEFINE) + (? + ^,[^,]+, + ) +) + +# Group 2 is defined on this line +^,([^,]+), + +(?:(?!(?&subcat)[\r\n]+(?&subcat)).)+ +''') + + TEST_DATA = ''' +,Cat 1, +,Brand 1, +some +thing +,Brand 2, +other +things +,Cat 2, +,Brand, +Some +thing +''' + + self.assertEqual([m.span(1, 2) for m in + TEST_REGEX.finditer(TEST_DATA)], [((-1, -1), (2, 7)), ((-1, -1), (54, + 59))]) + + # Hg issue 161: Unexpected fuzzy match results + self.assertEqual(regex.search('(abcdefgh){e}', + '******abcdefghijklmnopqrtuvwxyz', regex.BESTMATCH).span(), (6, 14)) + self.assertEqual(regex.search('(abcdefghi){e}', + '******abcdefghijklmnopqrtuvwxyz', regex.BESTMATCH).span(), (6, 15)) + + # Hg issue 163: allow lookarounds in conditionals. + self.assertEqual(regex.match(r'(?:(?=\d)\d+\b|\w+)', '123abc').span(), + (0, 6)) + self.assertEqual(regex.match(r'(?(?=\d)\d+\b|\w+)', '123abc'), None) + self.assertEqual(regex.search(r'(?(?<=love\s)you|(?<=hate\s)her)', + "I love you").span(), (7, 10)) + self.assertEqual(regex.findall(r'(?(?<=love\s)you|(?<=hate\s)her)', + "I love you but I don't hate her either"), ['you', 'her']) + + # Hg issue 180: bug of POSIX matching. + self.assertEqual(regex.search(r'(?p)a*(.*?)', 'aaabbb').group(0, 1), + ('aaabbb', 'bbb')) + self.assertEqual(regex.search(r'(?p)a*(.*)', 'aaabbb').group(0, 1), + ('aaabbb', 'bbb')) + self.assertEqual(regex.sub(r'(?p)a*(.*?)', r'\1', 'aaabbb'), 'bbb') + self.assertEqual(regex.sub(r'(?p)a*(.*)', r'\1', 'aaabbb'), 'bbb') + + # Hg issue 192: Named lists reverse matching doesn't work with + # IGNORECASE and V1 + self.assertEqual(regex.match(r'(?irV0)\L', '21', kw=['1']).span(), + (1, 2)) + self.assertEqual(regex.match(r'(?irV1)\L', '21', kw=['1']).span(), + (1, 2)) + + # Hg issue 193: Alternation and .REVERSE flag. + self.assertEqual(regex.search('a|b', '111a222').span(), (3, 4)) + self.assertEqual(regex.search('(?r)a|b', '111a222').span(), (3, 4)) + + # Hg issue 194: .FULLCASE and Backreference + self.assertEqual(regex.search(r'(?if)<(CLI)><\1>', + '').span(), (0, 10)) + self.assertEqual(regex.search(r'(?if)<(CLI)><\1>', + '').span(), (0, 10)) + self.assertEqual(regex.search(r'(?ifr)<\1><(CLI)>', + '').span(), (0, 10)) + + # Hg issue 195: Pickle (or otherwise serial) the compiled regex + r = regex.compile(r'\L', options=['foo', 'bar']) + p = pickle.dumps(r) + r = pickle.loads(p) + self.assertEqual(r.match('foo').span(), (0, 3)) + + # Hg issue 196: Fuzzy matching on repeated regex not working as + # expected + self.assertEqual(regex.match('(x{6}){e<=1}', 'xxxxxx', + flags=regex.BESTMATCH).span(), (0, 6)) + self.assertEqual(regex.match('(x{6}){e<=1}', 'xxxxx', + flags=regex.BESTMATCH).span(), (0, 5)) + self.assertEqual(regex.match('(x{6}){e<=1}', 'x', + flags=regex.BESTMATCH), None) + self.assertEqual(regex.match('(?r)(x{6}){e<=1}', 'xxxxxx', + flags=regex.BESTMATCH).span(), (0, 6)) + self.assertEqual(regex.match('(?r)(x{6}){e<=1}', 'xxxxx', + flags=regex.BESTMATCH).span(), (0, 5)) + self.assertEqual(regex.match('(?r)(x{6}){e<=1}', 'x', + flags=regex.BESTMATCH), None) + + # Hg issue 197: ValueError in regex.compile + self.assertRaises(regex.error, lambda: + regex.compile(b'00000\\0\\00\\^\50\\00\\U05000000')) + + # Hg issue 198: ValueError in regex.compile + self.assertRaises(regex.error, lambda: regex.compile(b"{e', '22', aa=['121', + '22'])), True) + self.assertEqual(bool(regex.search(r'(?ri)\L', '22', aa=['121', + '22'])), True) + self.assertEqual(bool(regex.search(r'(?fi)\L', '22', aa=['121', + '22'])), True) + self.assertEqual(bool(regex.search(r'(?fri)\L', '22', aa=['121', + '22'])), True) + + # Hg issue 208: Named list, (?ri) flags, Backreference + self.assertEqual(regex.search(r'(?r)\1dog..(?<=(\L))$', 'ccdogcc', + aa=['bcb', 'cc']). span(), (0, 7)) + self.assertEqual(regex.search(r'(?ir)\1dog..(?<=(\L))$', + 'ccdogcc', aa=['bcb', 'cc']). span(), (0, 7)) + + # Hg issue 210: Fuzzy matching and Backreference + self.assertEqual(regex.search(r'(2)(?:\1{5}){e<=1}', + '3222212').span(), (1, 7)) + self.assertEqual(regex.search(r'(\d)(?:\1{5}){e<=1}', + '3222212').span(), (1, 7)) + + # Hg issue 211: Segmentation fault with recursive matches and atomic + # groups + self.assertEqual(regex.match(r'''\A(?P(?>\((?&whole)\)|[+\-]))\Z''', + '((-))').span(), (0, 5)) + self.assertEqual(regex.match(r'''\A(?P(?>\((?&whole)\)|[+\-]))\Z''', + '((-)+)'), None) + + # Hg issue 212: Unexpected matching difference with .*? between re and + # regex + self.assertEqual(regex.match(r"x.*? (.).*\1(.*)\1", + 'x |y| z|').span(), (0, 9)) + self.assertEqual(regex.match(r"\.sr (.*?) (.)(.*)\2(.*)\2(.*)", + r'.sr h |||').span(), (0, 35)) + + # Hg issue 213: Segmentation Fault + a = '"\\xF9\\x80\\xAEqdz\\x95L\\xA7\\x89[\\xFE \\x91)\\xF9]\\xDB\'\\x99\\x09=\\x00\\xFD\\x98\\x22\\xDD\\xF1\\xB6\\xC3 Z\\xB6gv\\xA5x\\x93P\\xE1r\\x14\\x8Cv\\x0C\\xC0w\\x15r\\xFFc%" ' + py_regex_pattern = r'''(?P((?>(?"(?>\\.|[^\\"]+)+"|""|(?>'(?>\\.|[^\\']+)+')|''|(?>`(?>\\.|[^\\`]+)+`)|``)))) (?P((?>(?"(?>\\.|[^\\"]+)+"|""|(?>'(?>\\.|[^\\']+)+')|''|(?>`(?>\\.|[^\\`]+)+`)|``))))''' + self.assertEqual(bool(regex.search(py_regex_pattern, a)), False) + + # Hg Issue 216: Invalid match when using negative lookbehind and pipe + self.assertEqual(bool(regex.match('foo(?<=foo)', 'foo')), True) + self.assertEqual(bool(regex.match('foo(?.*\!\w*\:.*)|(?P.*))', + '!')), False) + + # Hg issue 220: Misbehavior of group capture with OR operand + self.assertEqual(regex.match(r'\w*(ea)\w*|\w*e(?!a)\w*', + 'easier').groups(), ('ea', )) + + # Hg issue 225: BESTMATCH in fuzzy match not working + self.assertEqual(regex.search('(^1234$){i,d}', '12234', + regex.BESTMATCH).span(), (0, 5)) + self.assertEqual(regex.search('(^1234$){i,d}', '12234', + regex.BESTMATCH).fuzzy_counts, (0, 1, 0)) + + self.assertEqual(regex.search('(^1234$){s,i,d}', '12234', + regex.BESTMATCH).span(), (0, 5)) + self.assertEqual(regex.search('(^1234$){s,i,d}', '12234', + regex.BESTMATCH).fuzzy_counts, (0, 1, 0)) + + # Hg issue 226: Error matching at start of string + self.assertEqual(regex.search('(^123$){s,i,d}', 'xxxxxxxx123', + regex.BESTMATCH).span(), (0, 11)) + self.assertEqual(regex.search('(^123$){s,i,d}', 'xxxxxxxx123', + regex.BESTMATCH).fuzzy_counts, (0, 8, 0)) + + # Hg issue 227: Incorrect behavior for ? operator with UNICODE + + # IGNORECASE + self.assertEqual(regex.search(r'a?yz', 'xxxxyz', flags=regex.FULLCASE | + regex.IGNORECASE).span(), (4, 6)) + + # Hg issue 230: Is it a bug of (?(DEFINE)...) + self.assertEqual(regex.findall(r'(?:(?![a-d]).)+', 'abcdefgh'), + ['efgh']) + self.assertEqual(regex.findall(r'''(?(DEFINE)(?P(?:(?![a-d]).)))(?&mydef)+''', + 'abcdefgh'), ['efgh']) + + # Hg issue 238: Not fully re backward compatible + self.assertEqual(regex.findall(r'((\w{1,3})(\.{2,10})){1,3}', + '"Erm....yes. T..T...Thank you for that."'), [('Erm....', 'Erm', + '....'), ('T...', 'T', '...')]) + self.assertEqual(regex.findall(r'((\w{1,3})(\.{2,10})){3}', + '"Erm....yes. T..T...Thank you for that."'), []) + self.assertEqual(regex.findall(r'((\w{1,3})(\.{2,10})){2}', + '"Erm....yes. T..T...Thank you for that."'), [('T...', 'T', '...')]) + self.assertEqual(regex.findall(r'((\w{1,3})(\.{2,10})){1}', + '"Erm....yes. T..T...Thank you for that."'), [('Erm....', 'Erm', + '....'), ('T..', 'T', '..'), ('T...', 'T', '...')]) + + # Hg issue 247: Unexpected result with fuzzy matching and lookahead + # expression + self.assertEqual(regex.search(r'(?:ESTONIA(?!\w)){e<=1}', + 'ESTONIAN WORKERS').group(), 'ESTONIAN') + self.assertEqual(regex.search(r'(?:ESTONIA(?=\W)){e<=1}', + 'ESTONIAN WORKERS').group(), 'ESTONIAN') + + self.assertEqual(regex.search(r'(?:(?.))(?&func)', + 'abc').groups(), (None, )) + self.assertEqual(regex.search(r'(?(DEFINE)(?.))(?&func)', + 'abc').groupdict(), {'func': None}) + self.assertEqual(regex.search(r'(?(DEFINE)(?.))(?&func)', + 'abc').capturesdict(), {'func': ['a']}) + + self.assertEqual(regex.search(r'(?(DEFINE)(?.))(?=(?&func))', + 'abc').groups(), (None, )) + self.assertEqual(regex.search(r'(?(DEFINE)(?.))(?=(?&func))', + 'abc').groupdict(), {'func': None}) + self.assertEqual(regex.search(r'(?(DEFINE)(?.))(?=(?&func))', + 'abc').capturesdict(), {'func': ['a']}) + + self.assertEqual(regex.search(r'(?(DEFINE)(?.)).(?<=(?&func))', + 'abc').groups(), (None, )) + self.assertEqual(regex.search(r'(?(DEFINE)(?.)).(?<=(?&func))', + 'abc').groupdict(), {'func': None}) + self.assertEqual(regex.search(r'(?(DEFINE)(?.)).(?<=(?&func))', + 'abc').capturesdict(), {'func': ['a']}) + + # Hg issue 271: Comment logic different between Re and Regex + self.assertEqual(bool(regex.match(r'ab(?#comment\))cd', 'abcd')), True) + + # Hg issue 276: Partial Matches yield incorrect matches and bounds + self.assertEqual(regex.search(r'[a-z]+ [a-z]*?:', 'foo bar', + partial=True).span(), (0, 7)) + self.assertEqual(regex.search(r'(?r):[a-z]*? [a-z]+', 'foo bar', + partial=True).span(), (0, 7)) + + # Hg issue 291: Include Script Extensions as a supported Unicode property + self.assertEqual(bool(regex.match(r'(?u)\p{Script:Beng}', + '\u09EF')), True) + self.assertEqual(bool(regex.match(r'(?u)\p{Script:Bengali}', + '\u09EF')), True) + self.assertEqual(bool(regex.match(r'(?u)\p{Script_Extensions:Bengali}', + '\u09EF')), True) + self.assertEqual(bool(regex.match(r'(?u)\p{Script_Extensions:Beng}', + '\u09EF')), True) + self.assertEqual(bool(regex.match(r'(?u)\p{Script_Extensions:Cakm}', + '\u09EF')), True) + self.assertEqual(bool(regex.match(r'(?u)\p{Script_Extensions:Sylo}', + '\u09EF')), True) + + # Hg issue #293: scx (Script Extensions) property currently matches + # incorrectly + self.assertEqual(bool(regex.match(r'(?u)\p{scx:Latin}', 'P')), True) + self.assertEqual(bool(regex.match(r'(?u)\p{scx:Ahom}', 'P')), False) + self.assertEqual(bool(regex.match(r'(?u)\p{scx:Common}', '4')), True) + self.assertEqual(bool(regex.match(r'(?u)\p{scx:Caucasian_Albanian}', '4')), + False) + self.assertEqual(bool(regex.match(r'(?u)\p{scx:Arabic}', '\u062A')), True) + self.assertEqual(bool(regex.match(r'(?u)\p{scx:Balinese}', '\u062A')), + False) + self.assertEqual(bool(regex.match(r'(?u)\p{scx:Devanagari}', '\u091C')), + True) + self.assertEqual(bool(regex.match(r'(?u)\p{scx:Batak}', '\u091C')), False) + + # Hg issue 296: Group references are not taken into account when group is reporting the last match + self.assertEqual(regex.fullmatch('(?P.)*(?&x)', 'abc').captures('x'), + ['a', 'b', 'c']) + self.assertEqual(regex.fullmatch('(?P.)*(?&x)', 'abc').group('x'), + 'b') + + self.assertEqual(regex.fullmatch('(?P.)(?P.)(?P.)', + 'abc').captures('x'), ['a', 'b', 'c']) + self.assertEqual(regex.fullmatch('(?P.)(?P.)(?P.)', + 'abc').group('x'), 'c') + + # Hg issue 299: Partial gives misleading results with "open ended" regexp + self.assertEqual(regex.match('(?:ab)*', 'ab', partial=True).partial, + False) + self.assertEqual(regex.match('(?:ab)*', 'abab', partial=True).partial, + False) + self.assertEqual(regex.match('(?:ab)*?', '', partial=True).partial, + False) + self.assertEqual(regex.match('(?:ab)*+', 'ab', partial=True).partial, + False) + self.assertEqual(regex.match('(?:ab)*+', 'abab', partial=True).partial, + False) + self.assertEqual(regex.match('(?:ab)+', 'ab', partial=True).partial, + False) + self.assertEqual(regex.match('(?:ab)+', 'abab', partial=True).partial, + False) + self.assertEqual(regex.match('(?:ab)+?', 'ab', partial=True).partial, + False) + self.assertEqual(regex.match('(?:ab)++', 'ab', partial=True).partial, + False) + self.assertEqual(regex.match('(?:ab)++', 'abab', partial=True).partial, + False) + + self.assertEqual(regex.match('(?r)(?:ab)*', 'ab', partial=True).partial, + False) + self.assertEqual(regex.match('(?r)(?:ab)*', 'abab', partial=True).partial, + False) + self.assertEqual(regex.match('(?r)(?:ab)*?', '', partial=True).partial, + False) + self.assertEqual(regex.match('(?r)(?:ab)*+', 'ab', partial=True).partial, + False) + self.assertEqual(regex.match('(?r)(?:ab)*+', 'abab', partial=True).partial, + False) + self.assertEqual(regex.match('(?r)(?:ab)+', 'ab', partial=True).partial, + False) + self.assertEqual(regex.match('(?r)(?:ab)+', 'abab', partial=True).partial, + False) + self.assertEqual(regex.match('(?r)(?:ab)+?', 'ab', partial=True).partial, + False) + self.assertEqual(regex.match('(?r)(?:ab)++', 'ab', partial=True).partial, + False) + self.assertEqual(regex.match('(?r)(?:ab)++', 'abab', partial=True).partial, + False) + + self.assertEqual(regex.match('a*', '', partial=True).partial, False) + self.assertEqual(regex.match('a*?', '', partial=True).partial, False) + self.assertEqual(regex.match('a*+', '', partial=True).partial, False) + self.assertEqual(regex.match('a+', '', partial=True).partial, True) + self.assertEqual(regex.match('a+?', '', partial=True).partial, True) + self.assertEqual(regex.match('a++', '', partial=True).partial, True) + self.assertEqual(regex.match('a+', 'a', partial=True).partial, False) + self.assertEqual(regex.match('a+?', 'a', partial=True).partial, False) + self.assertEqual(regex.match('a++', 'a', partial=True).partial, False) + + self.assertEqual(regex.match('(?r)a*', '', partial=True).partial, False) + self.assertEqual(regex.match('(?r)a*?', '', partial=True).partial, False) + self.assertEqual(regex.match('(?r)a*+', '', partial=True).partial, False) + self.assertEqual(regex.match('(?r)a+', '', partial=True).partial, True) + self.assertEqual(regex.match('(?r)a+?', '', partial=True).partial, True) + self.assertEqual(regex.match('(?r)a++', '', partial=True).partial, True) + self.assertEqual(regex.match('(?r)a+', 'a', partial=True).partial, False) + self.assertEqual(regex.match('(?r)a+?', 'a', partial=True).partial, False) + self.assertEqual(regex.match('(?r)a++', 'a', partial=True).partial, False) + + self.assertEqual(regex.match(r"(?:\s*\w+'*)+", 'whatever', partial=True).partial, + False) + + # Hg issue 300: segmentation fault + pattern = ('(?PGGCGTCACACTTTGCTATGCCATAGCAT[AG]TTTATCCATAAGA' + 'TTAGCGGATCCTACCTGACGCTTTTTATCGCAACTCTCTACTGTTTCTCCATAACAGAACATATTGA' + 'CTATCCGGTATTACCCGGCATGACAGGAGTAAAA){e<=1}' + '(?P[ACGT]{1059}){e<=2}' + '(?PTAATCGTCTTGTTTGATACACAAGGGTCGCATCTGCGGCCCTTTTGCTTTTTTAAG' + 'TTGTAAGGATATGCCATTCTAGA){e<=0}' + '(?P[ACGT]{18}){e<=0}' + '(?PAGATCGG[CT]AGAGCGTCGTGTAGGGAAAGAGTGTGG){e<=1}') + + text = ('GCACGGCGTCACACTTTGCTATGCCATAGCATATTTATCCATAAGATTAGCGGATCCTACC' + 'TGACGCTTTTTATCGCAACTCTCTACTGTTTCTCCATAACAGAACATATTGACTATCCGGTATTACC' + 'CGGCATGACAGGAGTAAAAATGGCTATCGACGAAAACAAACAGAAAGCGTTGGCGGCAGCACTGGGC' + 'CAGATTGAGAAACAATTTGGTAAAGGCTCCATCATGCGCCTGGGTGAAGACCGTTCCATGGATGTGG' + 'AAACCATCTCTACCGGTTCGCTTTCACTGGATATCGCGCTTGGGGCAGGTGGTCTGCCGATGGGCCG' + 'TATCGTCGAAATCTACGGACCGGAATCTTCCGGTAAAACCACGCTGACGCTGCAGGTGATCGCCGCA' + 'GCGCAGCGTGAAGGTAAAACCTGTGCGTTTATCGATGCTGAACACGCGCTGGACCCAATCTACGCAC' + 'GTAAACTGGGCGTCGATATCGACAACCTGCTGTGCTCCCAGCCGGACACCGGCGAGCAGGCACTGGA' + 'AATCTGTGACGCCCTGGCGCGTTCTGGCGCAGTAGACGTTATCGTCGTTGACTCCGTGGCGGCACTG' + 'ACGCCGAAAGCGGAAATCGAAGGCGAAATCGGCGACTCTCATATGGGCCTTGCGGCACGTATGATGA' + 'GCCAGGCGATGCGTAAGCTGGCGGGTAACCTGAAGCAGTCCAACACGCTGCTGATCTTCATCAACCC' + 'CATCCGTATGAAAATTGGTGTGATGTTCGGCAACCCGGAAACCACTTACCGGTGGTAACGCGCTGAA' + 'ATTCTACGCCTCTGTTCGTCTCGACATCCGTTAAATCGGCGCGGTGAAAGAGGGCGAAAACGTGGTG' + 'GGTAGCGAAACCCGCGTGAAAGTGGTGAAGAACAAAATCGCTGCGCCGTTTAAACAGGCTGAATTCC' + 'AGATCCTCTACGGCGAAGGTATCAACTTCTACCCCGAACTGGTTGACCTGGGCGTAAAAGAGAAGCT' + 'GATCGAGAAAGCAGGCGCGTGGTACAGCTACAAAGGTGAGAAGATCGGTCAGGGTAAAGCGAATGCG' + 'ACTGCCTGGCTGAAATTTAACCCGGAAACCGCGAAAGAGATCGAGTGAAAAGTACGTGAGTTGCTGC' + 'TGAGCAACCCGAACTCAACGCCGGATTTCTCTGTAGATGATAGCGAAGGCGTAGCAGAAACTAACGA' + 'AGATTTTTAATCGTCTTGTTTGATACACAAGGGTCGCATCTGCGGCCCTTTTGCTTTTTTAAGTTGT' + 'AAGGATATGCCATTCTAGACAGTTAACACACCAACAAAGATCGGTAGAGCGTCGTGTAGGGAAAGAG' + 'TGTGGTACC') + + m = regex.search(pattern, text, flags=regex.BESTMATCH) + self.assertEqual(m.fuzzy_counts, (0, 1, 0)) + self.assertEqual(m.fuzzy_changes, ([], [1206], [])) + + # Hg issue 306: Fuzzy match parameters not respecting quantifier scope + self.assertEqual(regex.search(r'(?e)(dogf(((oo){e<1})|((00){e<1}))d){e<2}', + 'dogfood').fuzzy_counts, (0, 0, 0)) + self.assertEqual(regex.search(r'(?e)(dogf(((oo){e<1})|((00){e<1}))d){e<2}', + 'dogfoot').fuzzy_counts, (1, 0, 0)) + + # Hg issue 312: \X not matching graphemes with zero-width-joins + self.assertEqual(regex.findall(r'\X', + '\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466'), + ['\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466']) + + # Hg issue 320: Abnormal performance + self.assertEqual(bool(regex.search(r'(?=a)a', 'a')), True) + self.assertEqual(bool(regex.search(r'(?!b)a', 'a')), True) + + # Hg issue 327: .fullmatch() causes MemoryError + self.assertEqual(regex.fullmatch(r'((\d)*?)*?', '123').span(), (0, 3)) + + # Hg issue 329: Wrong group matches when question mark quantifier is used within a look behind + self.assertEqual(regex.search(r'''(?(DEFINE)(?(?THIS_SHOULD_NOT_MATCHx?)|(?right))).*(?<=(?&mydef).*)''', + 'x right').capturesdict(), {'mydef': ['right'], 'wrong': [], 'right': + ['right']}) + + # Hg issue 338: specifying allowed characters when fuzzy-matching + self.assertEqual(bool(regex.match(r'(?:cat){e<=1:[u]}', 'cut')), True) + self.assertEqual(bool(regex.match(r'(?:cat){e<=1:u}', 'cut')), True) + + # Hg issue 353: fuzzy changes negative indexes + self.assertEqual(regex.search(r'(?be)(AGTGTTCCCCGCGCCAGCGGGGATAAACCG){s<=5,i<=5,d<=5,s+i+d<=10}', + 'TTCCCCGCGCCAGCGGGGATAAACCG').fuzzy_changes, ([], [], [0, 1, 3, 5])) + + # Git issue 364: Contradictory values in fuzzy_counts and fuzzy_changes + self.assertEqual(regex.match(r'(?:bc){e}', 'c').fuzzy_counts, (1, 0, + 1)) + self.assertEqual(regex.match(r'(?:bc){e}', 'c').fuzzy_changes, ([0], + [], [1])) + self.assertEqual(regex.match(r'(?e)(?:bc){e}', 'c').fuzzy_counts, (0, + 0, 1)) + self.assertEqual(regex.match(r'(?e)(?:bc){e}', 'c').fuzzy_changes, + ([], [], [0])) + self.assertEqual(regex.match(r'(?b)(?:bc){e}', 'c').fuzzy_counts, (0, + 0, 1)) + self.assertEqual(regex.match(r'(?b)(?:bc){e}', 'c').fuzzy_changes, + ([], [], [0])) + + # Git issue 370: Confusions about Fuzzy matching behavior + self.assertEqual(regex.match('(?e)(?:^(\\$ )?\\d{1,3}(,\\d{3})*(\\.\\d{2})$){e}', + '$ 10,112.111.12').fuzzy_counts, (6, 0, 5)) + self.assertEqual(regex.match('(?e)(?:^(\\$ )?\\d{1,3}(,\\d{3})*(\\.\\d{2})$){s<=1}', + '$ 10,112.111.12').fuzzy_counts, (1, 0, 0)) + self.assertEqual(regex.match('(?e)(?:^(\\$ )?\\d{1,3}(,\\d{3})*(\\.\\d{2})$){s<=1,i<=1,d<=1}', + '$ 10,112.111.12').fuzzy_counts, (1, 0, 0)) + self.assertEqual(regex.match('(?e)(?:^(\\$ )?\\d{1,3}(,\\d{3})*(\\.\\d{2})$){s<=3}', + '$ 10,1a2.111.12').fuzzy_counts, (2, 0, 0)) + self.assertEqual(regex.match('(?e)(?:^(\\$ )?\\d{1,3}(,\\d{3})*(\\.\\d{2})$){s<=2}', + '$ 10,1a2.111.12').fuzzy_counts, (2, 0, 0)) + + self.assertEqual(regex.fullmatch(r'(?e)(?:0?,0(?:,0)?){s<=1,d<=1}', + ',0;0').fuzzy_counts, (1, 0, 0)) + self.assertEqual(regex.fullmatch(r'(?e)(?:0??,0(?:,0)?){s<=1,d<=1}', + ',0;0').fuzzy_counts, (1, 0, 0)) + + # Git issue 371: Specifying character set when fuzzy-matching allows characters not in the set + self.assertEqual(regex.search(r"\b(?e)(?:\d{6,20}){i<=5:[\-\\\/]}\b", + "cat dog starting at 00:01132.000. hello world"), None) + + # Git issue 385: Comments in expressions + self.assertEqual(bool(regex.compile('(?#)')), True) + self.assertEqual(bool(regex.compile('(?x)(?#)')), True) + + # Git issue 394: Unexpected behaviour in fuzzy matching with limited character set with IGNORECASE flag + self.assertEqual(regex.findall(r'(\d+){i<=2:[ab]}', '123X4Y5'), + ['123', '4', '5']) + self.assertEqual(regex.findall(r'(?i)(\d+){i<=2:[ab]}', '123X4Y5'), + ['123', '4', '5']) + + # Git issue 403: Fuzzy matching with wrong distance (unnecessary substitutions) + self.assertEqual(regex.match(r'^(test){e<=5}$', 'terstin', + flags=regex.B).fuzzy_counts, (0, 3, 0)) + + # Git issue 408: regex fails with a quantified backreference but succeeds with repeated backref + self.assertEqual(bool(regex.match(r"(?:(x*)\1\1\1)*x$", "x" * 5)), True) + self.assertEqual(bool(regex.match(r"(?:(x*)\1{3})*x$", "x" * 5)), True) + + # Git issue 415: Fuzzy character restrictions don't apply to insertions at "right edge" + self.assertEqual(regex.match(r't(?:es){s<=1:\d}t', 'te5t').group(), + 'te5t') + self.assertEqual(regex.match(r't(?:es){s<=1:\d}t', 'tezt'), None) + self.assertEqual(regex.match(r't(?:es){i<=1:\d}t', 'tes5t').group(), + 'tes5t') + self.assertEqual(regex.match(r't(?:es){i<=1:\d}t', 'teszt'), None) + self.assertEqual(regex.match(r't(?:es){i<=1:\d}t', + 'tes5t').fuzzy_changes, ([], [3], [])) + self.assertEqual(regex.match(r't(es){i<=1,0.*)(?PCTTCC){e<=1}(?P([ACGT]){4,6})(?PCAATACCGACTCCTCACTGTGT){e<=2}(?P([ACGT]){0,6}$)' + + m = regex.match(pattern, sequence, flags=regex.BESTMATCH) + self.assertEqual(m.span(), (0, 50)) + self.assertEqual(m.groupdict(), {'insert': 'TTCAGACGTGTGCT', 'anchor': 'CTTCC', 'umi': 'GATCT', 'sid': 'CAATACCGACTCCTCACTGTGT', 'end': 'GTCT'}) + + m = regex.match(pattern, sequence, flags=regex.ENHANCEMATCH) + self.assertEqual(m.span(), (0, 50)) + self.assertEqual(m.groupdict(), {'insert': 'TTCAGACGTGTGCT', 'anchor': 'CTTCC', 'umi': 'GATCT', 'sid': 'CAATACCGACTCCTCACTGTGT', 'end': 'GTCT'}) + + # Git issue 433: Disagreement between fuzzy_counts and fuzzy_changes + pattern = r'(?P.*)(?PAACACTGG){e<=1}(?P([AT][CG]){5}){e<=2}(?PGTAACCGAAG){e<=2}(?P([ACGT]){0,6}$)' + + sequence = 'GGAAAACACTGGTCTCAGTCTCGTAACCGAAGTGGTCG' + m = regex.match(pattern, sequence, flags=regex.BESTMATCH) + self.assertEqual(m.fuzzy_counts, (0, 0, 0)) + self.assertEqual(m.fuzzy_changes, ([], [], [])) + + sequence = 'GGAAAACACTGGTCTCAGTCTCGTCCCCGAAGTGGTCG' + m = regex.match(pattern, sequence, flags=regex.BESTMATCH) + self.assertEqual(m.fuzzy_counts, (2, 0, 0)) + self.assertEqual(m.fuzzy_changes, ([24, 25], [], [])) + + # Git issue 439: Unmatched groups: sub vs subf + self.assertEqual(regex.sub(r'(test1)|(test2)', r'matched: \1\2', 'test1'), 'matched: test1') + self.assertEqual(regex.subf(r'(test1)|(test2)', r'matched: {1}{2}', 'test1'), 'matched: test1') + self.assertEqual(regex.search(r'(test1)|(test2)', 'matched: test1').expand(r'matched: \1\2'), 'matched: test1'), + self.assertEqual(regex.search(r'(test1)|(test2)', 'matched: test1').expandf(r'matched: {1}{2}'), 'matched: test1') + + # Git issue 442: Fuzzy regex matching doesn't seem to test insertions correctly + self.assertEqual(regex.search(r"(?:\bha\b){i:[ ]}", "having"), None) + self.assertEqual(regex.search(r"(?:\bha\b){i:[ ]}", "having", flags=regex.I), None) + + # Git issue 467: Scoped inline flags 'a', 'u' and 'L' affect global flags + self.assertEqual(regex.match(r'(?a:\w)\w', 'd\N{CYRILLIC SMALL LETTER ZHE}').span(), (0, 2)) + self.assertEqual(regex.match(r'(?a:\w)(?u:\w)', 'd\N{CYRILLIC SMALL LETTER ZHE}').span(), (0, 2)) + + # Git issue 473: Emoji classified as letter + self.assertEqual(regex.match(r'^\p{LC}+$', '\N{SMILING CAT FACE WITH OPEN MOUTH}'), None) + self.assertEqual(regex.match(r'^\p{So}+$', '\N{SMILING CAT FACE WITH OPEN MOUTH}').span(), (0, 1)) + + # Git issue 474: regex has no equivalent to `re.Match.groups()` for captures + self.assertEqual(regex.match(r'(.)+', 'abc').allcaptures(), (['abc'], ['a', 'b', 'c'])) + self.assertEqual(regex.match(r'(.)+', 'abc').allspans(), ([(0, 3)], [(0, 1), (1, 2), (2, 3)])) + + # Git issue 477: \v for vertical spacing + self.assertEqual(bool(regex.fullmatch(r'\p{HorizSpace}+', '\t \xA0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000')), True) + self.assertEqual(bool(regex.fullmatch(r'\p{VertSpace}+', '\n\v\f\r\x85\u2028\u2029')), True) + + # Git issue 479: Segmentation fault when using conditional pattern + self.assertEqual(regex.match(r'(?(?<=A)|(?(?![^B])C|D))', 'A'), None) + self.assertEqual(regex.search(r'(?(?<=A)|(?(?![^B])C|D))', 'A').span(), (1, 1)) + + # Git issue 494: Backtracking failure matching regex ^a?(a?)b?c\1$ against string abca + self.assertEqual(regex.search(r"^a?(a?)b?c\1$", "abca").span(), (0, 4)) + + # Git issue 498: Conditional negative lookahead inside positive lookahead fails to match + self.assertEqual(regex.match(r'(?(?=a).|..)', 'ab').span(), (0, 1)) + self.assertEqual(regex.match(r'(?(?=b).|..)', 'ab').span(), (0, 2)) + self.assertEqual(regex.match(r'(?(?!a).|..)', 'ab').span(), (0, 2)) + self.assertEqual(regex.match(r'(?(?!b).|..)', 'ab').span(), (0, 1)) + + # Git issue 525: segfault when fuzzy matching empty list + self.assertEqual(regex.match(r"(\L){e<=5}", "blah", foo=[]).span(), (0, 0)) + + # Git issue 527: `VERBOSE`/`X` flag breaks `\N` escapes + self.assertEqual(regex.compile(r'\N{LATIN SMALL LETTER A}').match('a').span(), (0, 1)) + self.assertEqual(regex.compile(r'\N{LATIN SMALL LETTER A}', flags=regex.X).match('a').span(), (0, 1)) + + # Git issue 539: Bug: Partial matching fails on a simple example + self.assertEqual(regex.match(r"[^/]*b/ccc", "b/ccc", partial=True).span(), (0, 5)) + self.assertEqual(regex.match(r"[^/]*b/ccc", "b/ccb", partial=True), None) + self.assertEqual(regex.match(r"[^/]*b/ccc", "b/cc", partial=True).span(), (0, 4)) + self.assertEqual(regex.match(r"[^/]*b/xyz", "b/xy", partial=True).span(), (0, 4)) + self.assertEqual(regex.match(r"[^/]*b/xyz", "b/yz", partial=True), None) + + self.assertEqual(regex.match(r"(?i)[^/]*b/ccc", "b/ccc", partial=True).span(), (0, 5)) + self.assertEqual(regex.match(r"(?i)[^/]*b/ccc", "b/ccb", partial=True), None) + self.assertEqual(regex.match(r"(?i)[^/]*b/ccc", "b/cc", partial=True).span(), (0, 4)) + self.assertEqual(regex.match(r"(?i)[^/]*b/xyz", "b/xy", partial=True).span(), (0, 4)) + self.assertEqual(regex.match(r"(?i)[^/]*b/xyz", "b/yz", partial=True), None) + + # Git issue 546: Partial match not working in some instances with non-greedy capture + self.assertEqual(bool(regex.match(r'.*?', '<', partial=True)), True) + self.assertEqual(bool(regex.match(r'.*?', '.*?', '', partial=True)), True) + self.assertEqual(bool(regex.match(r'.*?', 'x', partial=True)), True) + self.assertEqual(bool(regex.match(r'.*?', 'xyz abc', partial=True)), True) + self.assertEqual(bool(regex.match(r'.*?', 'xyz abc foo', partial=True)), True) + self.assertEqual(bool(regex.match(r'.*?', 'xyz abc foo ', partial=True)), True) + self.assertEqual(bool(regex.match(r'.*?', 'xyz abc foo bar', partial=True)), True) + + def test_fuzzy_ext(self): + self.assertEqual(bool(regex.fullmatch(r'(?r)(?:a){e<=1:[a-z]}', 'e')), + True) + self.assertEqual(bool(regex.fullmatch(r'(?:a){e<=1:[a-z]}', 'e')), + True) + self.assertEqual(bool(regex.fullmatch(r'(?:a){e<=1:[a-z]}', '-')), + False) + self.assertEqual(bool(regex.fullmatch(r'(?r)(?:a){e<=1:[a-z]}', '-')), + False) + + self.assertEqual(bool(regex.fullmatch(r'(?:a){e<=1:[a-z]}', 'ae')), + True) + self.assertEqual(bool(regex.fullmatch(r'(?r)(?:a){e<=1:[a-z]}', + 'ae')), True) + self.assertEqual(bool(regex.fullmatch(r'(?:a){e<=1:[a-z]}', 'a-')), + False) + self.assertEqual(bool(regex.fullmatch(r'(?r)(?:a){e<=1:[a-z]}', + 'a-')), False) + + self.assertEqual(bool(regex.fullmatch(r'(?:ab){e<=1:[a-z]}', 'ae')), + True) + self.assertEqual(bool(regex.fullmatch(r'(?r)(?:ab){e<=1:[a-z]}', + 'ae')), True) + self.assertEqual(bool(regex.fullmatch(r'(?:ab){e<=1:[a-z]}', 'a-')), + False) + self.assertEqual(bool(regex.fullmatch(r'(?r)(?:ab){e<=1:[a-z]}', + 'a-')), False) + + self.assertEqual(bool(regex.fullmatch(r'(a)\1{e<=1:[a-z]}', 'ae')), + True) + self.assertEqual(bool(regex.fullmatch(r'(?r)\1{e<=1:[a-z]}(a)', + 'ea')), True) + self.assertEqual(bool(regex.fullmatch(r'(a)\1{e<=1:[a-z]}', 'a-')), + False) + self.assertEqual(bool(regex.fullmatch(r'(?r)\1{e<=1:[a-z]}(a)', + '-a')), False) + + self.assertEqual(bool(regex.fullmatch(r'(?fiu)(?:\N{LATIN SMALL LETTER SHARP S}){e<=1:[a-z]}', + 'ts')), True) + self.assertEqual(bool(regex.fullmatch(r'(?fiu)(?:\N{LATIN SMALL LETTER SHARP S}){e<=1:[a-z]}', + 'st')), True) + self.assertEqual(bool(regex.fullmatch(r'(?firu)(?:\N{LATIN SMALL LETTER SHARP S}){e<=1:[a-z]}', + 'st')), True) + self.assertEqual(bool(regex.fullmatch(r'(?firu)(?:\N{LATIN SMALL LETTER SHARP S}){e<=1:[a-z]}', + 'ts')), True) + self.assertEqual(bool(regex.fullmatch(r'(?fiu)(?:\N{LATIN SMALL LETTER SHARP S}){e<=1:[a-z]}', + '-s')), False) + self.assertEqual(bool(regex.fullmatch(r'(?fiu)(?:\N{LATIN SMALL LETTER SHARP S}){e<=1:[a-z]}', + 's-')), False) + self.assertEqual(bool(regex.fullmatch(r'(?firu)(?:\N{LATIN SMALL LETTER SHARP S}){e<=1:[a-z]}', + 's-')), False) + self.assertEqual(bool(regex.fullmatch(r'(?firu)(?:\N{LATIN SMALL LETTER SHARP S}){e<=1:[a-z]}', + '-s')), False) + + self.assertEqual(bool(regex.fullmatch(r'(?fiu)(\N{LATIN SMALL LETTER SHARP S})\1{e<=1:[a-z]}', + 'ssst')), True) + self.assertEqual(bool(regex.fullmatch(r'(?fiu)(\N{LATIN SMALL LETTER SHARP S})\1{e<=1:[a-z]}', + 'ssts')), True) + self.assertEqual(bool(regex.fullmatch(r'(?firu)\1{e<=1:[a-z]}(\N{LATIN SMALL LETTER SHARP S})', + 'stss')), True) + self.assertEqual(bool(regex.fullmatch(r'(?firu)\1{e<=1:[a-z]}(\N{LATIN SMALL LETTER SHARP S})', + 'tsss')), True) + self.assertEqual(bool(regex.fullmatch(r'(?fiu)(\N{LATIN SMALL LETTER SHARP S})\1{e<=1:[a-z]}', + 'ss-s')), False) + self.assertEqual(bool(regex.fullmatch(r'(?fiu)(\N{LATIN SMALL LETTER SHARP S})\1{e<=1:[a-z]}', + 'sss-')), False) + self.assertEqual(bool(regex.fullmatch(r'(?firu)(\N{LATIN SMALL LETTER SHARP S})\1{e<=1:[a-z]}', + '-s')), False) + self.assertEqual(bool(regex.fullmatch(r'(?firu)(\N{LATIN SMALL LETTER SHARP S})\1{e<=1:[a-z]}', + 's-')), False) + + self.assertEqual(bool(regex.fullmatch(r'(?fiu)(ss)\1{e<=1:[a-z]}', + '\N{LATIN SMALL LETTER SHARP S}ts')), True) + self.assertEqual(bool(regex.fullmatch(r'(?fiu)(ss)\1{e<=1:[a-z]}', + '\N{LATIN SMALL LETTER SHARP S}st')), True) + self.assertEqual(bool(regex.fullmatch(r'(?firu)\1{e<=1:[a-z]}(ss)', + 'st\N{LATIN SMALL LETTER SHARP S}')), True) + self.assertEqual(bool(regex.fullmatch(r'(?firu)\1{e<=1:[a-z]}(ss)', + 'ts\N{LATIN SMALL LETTER SHARP S}')), True) + self.assertEqual(bool(regex.fullmatch(r'(?fiu)(ss)\1{e<=1:[a-z]}', + '\N{LATIN SMALL LETTER SHARP S}-s')), False) + self.assertEqual(bool(regex.fullmatch(r'(?fiu)(ss)\1{e<=1:[a-z]}', + '\N{LATIN SMALL LETTER SHARP S}s-')), False) + self.assertEqual(bool(regex.fullmatch(r'(?firu)(ss)\1{e<=1:[a-z]}', + 's-\N{LATIN SMALL LETTER SHARP S}')), False) + self.assertEqual(bool(regex.fullmatch(r'(?firu)(ss)\1{e<=1:[a-z]}', + '-s\N{LATIN SMALL LETTER SHARP S}')), False) + + def test_subscripted_captures(self): + self.assertEqual(regex.match(r'(?P.)+', + 'abc').expandf('{0} {0[0]} {0[-1]}'), 'abc abc abc') + self.assertEqual(regex.match(r'(?P.)+', + 'abc').expandf('{1} {1[0]} {1[1]} {1[2]} {1[-1]} {1[-2]} {1[-3]}'), + 'c a b c c b a') + self.assertEqual(regex.match(r'(?P.)+', + 'abc').expandf('{x} {x[0]} {x[1]} {x[2]} {x[-1]} {x[-2]} {x[-3]}'), + 'c a b c c b a') + + self.assertEqual(regex.subf(r'(?P.)+', r'{0} {0[0]} {0[-1]}', + 'abc'), 'abc abc abc') + self.assertEqual(regex.subf(r'(?P.)+', + '{1} {1[0]} {1[1]} {1[2]} {1[-1]} {1[-2]} {1[-3]}', 'abc'), + 'c a b c c b a') + self.assertEqual(regex.subf(r'(?P.)+', + '{x} {x[0]} {x[1]} {x[2]} {x[-1]} {x[-2]} {x[-3]}', 'abc'), + 'c a b c c b a') + + def test_more_zerowidth(self): + if sys.version_info >= (3, 7, 0): + self.assertEqual(regex.split(r'\b|:+', 'a::bc'), ['', 'a', '', '', + 'bc', '']) + self.assertEqual(regex.sub(r'\b|:+', '-', 'a::bc'), '-a---bc-') + self.assertEqual(regex.findall(r'\b|:+', 'a::bc'), ['', '', '::', + '', '']) + self.assertEqual([m.span() for m in regex.finditer(r'\b|:+', + 'a::bc')], [(0, 0), (1, 1), (1, 3), (3, 3), (5, 5)]) + self.assertEqual([m.span() for m in regex.finditer(r'(?m)^\s*?$', + 'foo\n\n\nbar')], [(4, 4), (4, 5), (5, 5)]) + + def test_line_ending(self): + self.assertEqual(regex.findall(r'\R', '\r\n\n\x0B\f\r\x85\u2028\u2029'), + ['\r\n', '\n', '\x0B', '\f', '\r', '\x85', '\u2028', '\u2029']) + self.assertEqual(regex.findall(br'\R', b'\r\n\n\x0B\f\r\x85'), [b'\r\n', + b'\n', b'\x0B', b'\f', b'\r']) + +#def test_main(): +# unittest.main(verbosity=2) + +#if __name__ == "__main__": +# test_main() \ No newline at end of file diff --git a/setup.py b/setup.py index 86fa783ff..19af57477 100644 --- a/setup.py +++ b/setup.py @@ -86,6 +86,13 @@ def rust_build(setup_kwargs: Dict[str, Any]) -> None: extra_compile_args=COMPILE_FLAGS, extra_link_args=["-Lthird_party/cyan4973"], # Link Abseil library ), + Extension( + name="opteryx.third_party.mrabarnett.regex._regex", + sources=[ + "third_party/mrabarnett/_regex.c", + "third_party/mrabarnett/_regex_unicode.c" + ] + ), Extension( name="opteryx.compiled.functions.functions", sources=["opteryx/compiled/functions/functions.pyx"], diff --git a/tests/query_planner/test_r_strings.py b/tests/query_planner/test_r_strings.py new file mode 100644 index 000000000..4c4b1a02b --- /dev/null +++ b/tests/query_planner/test_r_strings.py @@ -0,0 +1,55 @@ +import os +import sys + +import pytest + +sys.path.insert(1, os.path.join(sys.path[0], "../..")) + +from opteryx.planner.sql_rewriter import sql_parts + +# Define the test cases as a list of (input, expected_output) tuples +# fmt:off +test_cases = [ + ("This is a test string with r'abc' and R\"def\".", "This is a test string with BASE85_DECODE('VPaz') and BASE85_DECODE('WMyU')."), + ("r'123' should become BASE85_DECODE('F)}j')", "BASE85_DECODE('F)}j') should become BASE85_DECODE('F)}j')"), + ('R"xyz" should become BASE85_DECODE(\'czJp\')', 'BASE85_DECODE(\'czJp\') should become BASE85_DECODE(\'czJp\')'), + ("Mix of r'one' and R\"two\"", "Mix of BASE85_DECODE('Z*FA') and BASE85_DECODE('ba!t')"), + ("No prefixed strings here.", "No prefixed strings here."), + ("R'' and r\"\" should be handled.", "BASE85_DECODE('') and BASE85_DECODE('') should be handled."), + ("I am escaping r'\\1' and R'\\1'", "I am escaping BASE85_DECODE('Trm') and BASE85_DECODE('Trm')"), + ("I am also escaping r'\1' and r'\1'", "I am also escaping BASE85_DECODE('0R') and BASE85_DECODE('0R')"), +] +# fmt:on + + +@pytest.mark.parametrize("input_text, expected_output", test_cases) +def test_replace_b_strings(input_text, expected_output): + assert " ".join(sql_parts(input_text)).replace(" ", "") == expected_output.replace(" ", "") + + +if __name__ == "__main__": # pragma: no cover + """ + Running in the IDE we do some formatting - it's not functional but helps + when reading the outputs. + """ + + import shutil + import time + + width = shutil.get_terminal_size((80, 20))[0] - 15 + + print(f"RUNNING BATTERY OF {len(test_cases)} R(aw) STRINGS") + for index, (case, expected) in enumerate(test_cases): + start = time.monotonic_ns() + print( + f"\033[0;36m{(index + 1):04}\033[0m {case[0:width - 1].ljust(width)}", + end="", + ) + if " ".join(sql_parts(case)).replace(" ", "") == expected.replace(" ", ""): + print(f"\033[0;32m{str(int((time.monotonic_ns() - start)/1e6)).rjust(4)}ms\033[0m ✅") + else: + print(f"\033[0;31m{str(int((time.monotonic_ns() - start)/1e6)).rjust(4)}ms\033[0m ❌") + print("Expected:", expected) + print("Recieved:", " ".join(sql_parts(case))) + + print("--- ✅ \033[0;32mdone\033[0m") diff --git a/tests/sql_battery/tests/clickbench.run_tests b/tests/sql_battery/tests/clickbench.run_tests index d1cfe8252..21664e159 100644 --- a/tests/sql_battery/tests/clickbench.run_tests +++ b/tests/sql_battery/tests/clickbench.run_tests @@ -26,7 +26,7 @@ SELECT SearchPhrase FROM testdata.clickbench_tiny WHERE SearchPhrase <> '' ORDER SELECT SearchPhrase FROM testdata.clickbench_tiny WHERE SearchPhrase <> '' ORDER BY SearchPhrase LIMIT 10; SELECT SearchPhrase FROM testdata.clickbench_tiny WHERE SearchPhrase <> '' ORDER BY EventTime, SearchPhrase LIMIT 10; SELECT CounterID, AVG(length(URL)) AS l, COUNT(*) AS c FROM testdata.clickbench_tiny WHERE URL <> '' GROUP BY CounterID HAVING COUNT(*) > 100000 ORDER BY l DESC LIMIT 25; -SELECT REGEXP_REPLACE(Referer, '^https?://(?:www\.)?([^/]+)/.*$', '\1') AS k, AVG(length(Referer)) AS l, COUNT(*) AS c, MIN(Referer) FROM testdata.clickbench_tiny WHERE Referer <> '' GROUP BY REGEXP_REPLACE(Referer, '^https?://(?:www\.)?([^/]+)/.*$', '\1') HAVING COUNT(*) > 100000 ORDER BY l DESC LIMIT 25; +SELECT REGEXP_REPLACE(Referer, b'^https?://(?:www\.)?([^/]+)/.*$', r'\\1') AS k, AVG(length(Referer)) AS l, COUNT(*) AS c, MIN(Referer) FROM testdata.clickbench_tiny WHERE Referer <> '' GROUP BY REGEXP_REPLACE(Referer, b'^https?://(?:www\.)?([^/]+)/.*$', r'\\1') HAVING COUNT(*) > 100000 ORDER BY l DESC LIMIT 25; SELECT SUM(ResolutionWidth), SUM(ResolutionWidth + 1), SUM(ResolutionWidth + 2), SUM(ResolutionWidth + 3), SUM(ResolutionWidth + 4), SUM(ResolutionWidth + 5), SUM(ResolutionWidth + 6), SUM(ResolutionWidth + 7), SUM(ResolutionWidth + 8), SUM(ResolutionWidth + 9), SUM(ResolutionWidth + 10), SUM(ResolutionWidth + 11), SUM(ResolutionWidth + 12), SUM(ResolutionWidth + 13), SUM(ResolutionWidth + 14), SUM(ResolutionWidth + 15), SUM(ResolutionWidth + 16), SUM(ResolutionWidth + 17), SUM(ResolutionWidth + 18), SUM(ResolutionWidth + 19), SUM(ResolutionWidth + 20), SUM(ResolutionWidth + 21), SUM(ResolutionWidth + 22), SUM(ResolutionWidth + 23), SUM(ResolutionWidth + 24), SUM(ResolutionWidth + 25), SUM(ResolutionWidth + 26), SUM(ResolutionWidth + 27), SUM(ResolutionWidth + 28), SUM(ResolutionWidth + 29), SUM(ResolutionWidth + 30), SUM(ResolutionWidth + 31), SUM(ResolutionWidth + 32), SUM(ResolutionWidth + 33), SUM(ResolutionWidth + 34), SUM(ResolutionWidth + 35), SUM(ResolutionWidth + 36), SUM(ResolutionWidth + 37), SUM(ResolutionWidth + 38), SUM(ResolutionWidth + 39), SUM(ResolutionWidth + 40), SUM(ResolutionWidth + 41), SUM(ResolutionWidth + 42), SUM(ResolutionWidth + 43), SUM(ResolutionWidth + 44), SUM(ResolutionWidth + 45), SUM(ResolutionWidth + 46), SUM(ResolutionWidth + 47), SUM(ResolutionWidth + 48), SUM(ResolutionWidth + 49), SUM(ResolutionWidth + 50), SUM(ResolutionWidth + 51), SUM(ResolutionWidth + 52), SUM(ResolutionWidth + 53), SUM(ResolutionWidth + 54), SUM(ResolutionWidth + 55), SUM(ResolutionWidth + 56), SUM(ResolutionWidth + 57), SUM(ResolutionWidth + 58), SUM(ResolutionWidth + 59), SUM(ResolutionWidth + 60), SUM(ResolutionWidth + 61), SUM(ResolutionWidth + 62), SUM(ResolutionWidth + 63), SUM(ResolutionWidth + 64), SUM(ResolutionWidth + 65), SUM(ResolutionWidth + 66), SUM(ResolutionWidth + 67), SUM(ResolutionWidth + 68), SUM(ResolutionWidth + 69), SUM(ResolutionWidth + 70), SUM(ResolutionWidth + 71), SUM(ResolutionWidth + 72), SUM(ResolutionWidth + 73), SUM(ResolutionWidth + 74), SUM(ResolutionWidth + 75), SUM(ResolutionWidth + 76), SUM(ResolutionWidth + 77), SUM(ResolutionWidth + 78), SUM(ResolutionWidth + 79), SUM(ResolutionWidth + 80), SUM(ResolutionWidth + 81), SUM(ResolutionWidth + 82), SUM(ResolutionWidth + 83), SUM(ResolutionWidth + 84), SUM(ResolutionWidth + 85), SUM(ResolutionWidth + 86), SUM(ResolutionWidth + 87), SUM(ResolutionWidth + 88), SUM(ResolutionWidth + 89) FROM testdata.clickbench_tiny; SELECT SearchEngineID, ClientIP, COUNT(*) AS c, SUM(IsRefresh), AVG(ResolutionWidth) FROM testdata.clickbench_tiny WHERE SearchPhrase <> '' GROUP BY SearchEngineID, ClientIP ORDER BY c DESC LIMIT 10; SELECT WatchID, ClientIP, COUNT(*) AS c, SUM(IsRefresh), AVG(ResolutionWidth) FROM testdata.clickbench_tiny WHERE SearchPhrase <> '' GROUP BY WatchID, ClientIP ORDER BY c DESC LIMIT 10; diff --git a/third_party/mrabarnett/LICENSE.txt b/third_party/mrabarnett/LICENSE.txt new file mode 100644 index 000000000..ed60d0edf --- /dev/null +++ b/third_party/mrabarnett/LICENSE.txt @@ -0,0 +1,208 @@ +This work was derived from the 're' module of CPython 2.6 and CPython 3.1, +copyright (c) 1998-2001 by Secret Labs AB and licensed under CNRI's Python 1.6 +license. + +All additions and alterations are licensed under the Apache 2.0 License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2020 Matthew Barnett + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/third_party/mrabarnett/_regex.c b/third_party/mrabarnett/_regex.c new file mode 100644 index 000000000..44970a759 --- /dev/null +++ b/third_party/mrabarnett/_regex.c @@ -0,0 +1,26328 @@ +/* Secret Labs' Regular Expression Engine + * + * regular expression matching engine + * + * partial history: + * 1999-10-24 fl created (based on existing template matcher code) + * 2000-03-06 fl first alpha, sort of + * 2000-08-01 fl fixes for 1.6b1 + * 2000-08-07 fl use PyOS_CheckStack() if available + * 2000-09-20 fl added expand method + * 2001-03-20 fl lots of fixes for 2.1b2 + * 2001-04-15 fl export copyright as Python attribute, not global + * 2001-04-28 fl added __copy__ methods (work in progress) + * 2001-05-14 fl fixes for 1.5.2 compatibility + * 2001-07-01 fl added BIGCHARSET support (from Martin von Loewis) + * 2001-10-18 fl fixed group reset issue (from Matthew Mueller) + * 2001-10-20 fl added split primitive; reenable unicode for 1.6/2.0/2.1 + * 2001-10-21 fl added sub/subn primitive + * 2001-10-24 fl added finditer primitive (for 2.2 only) + * 2001-12-07 fl fixed memory leak in sub/subn (Guido van Rossum) + * 2002-11-09 fl fixed empty sub/subn return type + * 2003-04-18 mvl fully support 4-byte codes + * 2003-10-17 gn implemented non recursive scheme + * 2009-07-26 mrab completely re-designed matcher code + * 2011-11-18 mrab added support for PEP 393 strings + * + * Copyright (c) 1997-2001 by Secret Labs AB. All rights reserved. + * + * This version of the SRE library can be redistributed under CNRI's + * Python 1.6 license. For any other use, please contact Secret Labs + * AB (info@pythonware.com). + * + * Portions of this engine have been developed in cooperation with + * CNRI. Hewlett-Packard provided funding for 1.6 integration and + * other compatibility work. + */ + +/* #define VERBOSE */ + +#define RE_MEMORY_LIMIT 0x40000000 + +#if defined(VERBOSE) +#define TRACE(X) printf X; +#else +#define TRACE(X) +#endif + +#define PY_SSIZE_T_CLEAN + +#include "Python.h" +#include "structmember.h" /* offsetof */ +#include +#include +#include "_regex.h" +#include "pyport.h" +#include "pythread.h" + +typedef RE_UINT32 RE_CODE; +typedef unsigned char BYTE; + +/* Properties in the General Category. */ +#define RE_PROP_GC_CN ((RE_PROP_GC << 16) | RE_PROP_CN) +#define RE_PROP_GC_LU ((RE_PROP_GC << 16) | RE_PROP_LU) +#define RE_PROP_GC_LL ((RE_PROP_GC << 16) | RE_PROP_LL) +#define RE_PROP_GC_LT ((RE_PROP_GC << 16) | RE_PROP_LT) +#define RE_PROP_GC_P ((RE_PROP_GC << 16) | RE_PROP_P) + +/* Unlimited repeat count. */ +#define RE_UNLIMITED (~(RE_CODE)0) + +/* The status of a . */ +typedef RE_UINT32 RE_STATUS_T; + +/* Whether to match concurrently, i.e. release the GIL while matching. */ +#define RE_CONC_NO 0 +#define RE_CONC_YES 1 +#define RE_CONC_DEFAULT 2 + +/* The result of decoding the timeout. Values are in clock ticks. Non-negative + * values are valid. + */ +#define RE_NO_TIMEOUT -1 +#define RE_BAD_TIMEOUT -2 + +/* The side that could truncate in a partial match. + * + * The values RE_PARTIAL_LEFT and RE_PARTIAL_RIGHT are also used as array + * indexes, so they need to be 0 and 1. + */ +#define RE_PARTIAL_NONE -1 +#define RE_PARTIAL_LEFT 0 +#define RE_PARTIAL_RIGHT 1 + +/* Flags for the kind of 'sub' call: 'sub', 'subn', 'subf', 'subfn'. */ +#define RE_SUB 0x0 +#define RE_SUBN 0x1 +#define RE_SUBF 0x2 + +/* Error codes. */ +#define RE_ERROR_INITIALISING 2 /* Initialising object. */ +#define RE_ERROR_SUCCESS 1 /* Successful match. */ +#define RE_ERROR_FAILURE 0 /* Unsuccessful match. */ +#define RE_ERROR_ILLEGAL -1 /* Illegal code. */ +#define RE_ERROR_INTERNAL -2 /* Internal error. */ +#define RE_ERROR_CONCURRENT -3 /* "concurrent" invalid. */ +#define RE_ERROR_MEMORY -4 /* Out of memory. */ +#define RE_ERROR_CANCELLED -5 /* Matching cancelled. */ +#define RE_ERROR_REPLACEMENT -6 /* Invalid replacement string. */ +#define RE_ERROR_INVALID_GROUP_REF -7 /* Invalid group reference. */ +#define RE_ERROR_GROUP_INDEX_TYPE -8 /* Group index type error. */ +#define RE_ERROR_NO_SUCH_GROUP -9 /* No such group. */ +#define RE_ERROR_INDEX -10 /* String index. */ +#define RE_ERROR_NOT_STRING -11 /* Not a string. */ +#define RE_ERROR_NOT_UNICODE -12 /* Not a Unicode string. */ +#define RE_ERROR_PARTIAL -13 /* Partial match. */ +#define RE_ERROR_NOT_BYTES -14 /* Not a bytestring. */ +#define RE_ERROR_BAD_TIMEOUT -15 /* "timeout" invalid. */ +#define RE_ERROR_TIMED_OUT -16 /* Matching has timed out. */ + +/* Node bitflags. */ +#define RE_POSITIVE_OP 0x1 +#define RE_ZEROWIDTH_OP 0x2 +#define RE_FUZZY_OP 0x4 +#define RE_REVERSE_OP 0x8 +#define RE_REQUIRED_OP 0x10 + +/* Guards against further matching can occur at the start of the body and the + * tail of a repeat containing a repeat. + */ +#define RE_STATUS_BODY 0x1 +#define RE_STATUS_TAIL 0x2 + +/* Whether a guard is added depends on whether there's a repeat in the body of + * the repeat or a group reference in the body or tail of the repeat. + */ +#define RE_STATUS_NEITHER 0x0 +#define RE_STATUS_REPEAT 0x4 +#define RE_STATUS_LIMITED 0x8 +#define RE_STATUS_REF 0x10 +#define RE_STATUS_VISITED_AG 0x20 +#define RE_STATUS_VISITED_REP 0x40 + +/* Whether a string node has been initialised for fast searching. */ +#define RE_STATUS_FAST_INIT 0x80 + +/* Whether a node us being used. (Additional nodes may be created while the + * pattern is being built. + */ +#define RE_STATUS_USED 0x100 + +/* Whether a node is a string node. */ +#define RE_STATUS_STRING 0x200 + +/* Whether a repeat node is within another repeat. */ +#define RE_STATUS_INNER 0x400 + +/* Various flags stored in a node status member. */ +#define RE_STATUS_SHIFT 11 + +#define RE_STATUS_FUZZY (RE_FUZZY_OP << RE_STATUS_SHIFT) +#define RE_STATUS_REVERSE (RE_REVERSE_OP << RE_STATUS_SHIFT) +#define RE_STATUS_REQUIRED (RE_REQUIRED_OP << RE_STATUS_SHIFT) +#define RE_STATUS_HAS_GROUPS 0x10000 +#define RE_STATUS_HAS_REPEATS 0x20000 +#define RE_STATUS_ALL_ATOMIC 0x40000 + +/* The different error types for fuzzy matching. */ +#define RE_FUZZY_SUB 0 +#define RE_FUZZY_INS 1 +#define RE_FUZZY_DEL 2 +#define RE_FUZZY_ERR 3 +#define RE_FUZZY_COUNT 3 + +/* The various values in a FUZZY node. */ +#define RE_FUZZY_VAL_MIN_BASE 1 +#define RE_FUZZY_VAL_MIN_SUB (RE_FUZZY_VAL_MIN_BASE + RE_FUZZY_SUB) +#define RE_FUZZY_VAL_MIN_INS (RE_FUZZY_VAL_MIN_BASE + RE_FUZZY_INS) +#define RE_FUZZY_VAL_MIN_DEL (RE_FUZZY_VAL_MIN_BASE + RE_FUZZY_DEL) +#define RE_FUZZY_VAL_MIN_ERR (RE_FUZZY_VAL_MIN_BASE + RE_FUZZY_ERR) + +#define RE_FUZZY_VAL_MAX_BASE 5 +#define RE_FUZZY_VAL_MAX_SUB (RE_FUZZY_VAL_MAX_BASE + RE_FUZZY_SUB) +#define RE_FUZZY_VAL_MAX_INS (RE_FUZZY_VAL_MAX_BASE + RE_FUZZY_INS) +#define RE_FUZZY_VAL_MAX_DEL (RE_FUZZY_VAL_MAX_BASE + RE_FUZZY_DEL) +#define RE_FUZZY_VAL_MAX_ERR (RE_FUZZY_VAL_MAX_BASE + RE_FUZZY_ERR) + +#define RE_FUZZY_VAL_COST_BASE 9 +#define RE_FUZZY_VAL_SUB_COST (RE_FUZZY_VAL_COST_BASE + RE_FUZZY_SUB) +#define RE_FUZZY_VAL_INS_COST (RE_FUZZY_VAL_COST_BASE + RE_FUZZY_INS) +#define RE_FUZZY_VAL_DEL_COST (RE_FUZZY_VAL_COST_BASE + RE_FUZZY_DEL) +#define RE_FUZZY_VAL_MAX_COST (RE_FUZZY_VAL_COST_BASE + RE_FUZZY_ERR) + +/* The maximum number of errors when trying to improve a fuzzy match. */ +#define RE_MAX_ERRORS 10 + +/* The flags which will be set for full Unicode case folding. */ +#define RE_FULL_CASE_FOLDING (RE_FLAG_UNICODE | RE_FLAG_FULLCASE | RE_FLAG_IGNORECASE) + +/* The shortest string prefix for which we'll use a fast string search. */ +#define RE_MIN_FAST_LENGTH 5 + +static char copyright[] = + " RE 2.3.0 Copyright (c) 1997-2002 by Secret Labs AB "; + +/* The exception to raise on error. */ +static PyObject* error_exception; + +/* The dictionary of Unicode properties. */ +static PyObject* property_dict; + +typedef struct RE_State* RE_StatePtr; + +/* Bit-flags for the common character properties supported by locale-sensitive + * matching. + */ +#define RE_LOCALE_ALNUM 0x001 +#define RE_LOCALE_ALPHA 0x002 +#define RE_LOCALE_CNTRL 0x004 +#define RE_LOCALE_DIGIT 0x008 +#define RE_LOCALE_GRAPH 0x010 +#define RE_LOCALE_LOWER 0x020 +#define RE_LOCALE_PRINT 0x040 +#define RE_LOCALE_PUNCT 0x080 +#define RE_LOCALE_SPACE 0x100 +#define RE_LOCALE_UPPER 0x200 + +/* Info about the current locale. + * + * Used by patterns that are locale-sensitive. + */ +typedef struct RE_LocaleInfo { + unsigned short properties[0x100]; + unsigned char uppercase[0x100]; + unsigned char lowercase[0x100]; +} RE_LocaleInfo; + +/* Handlers for ASCII, locale and Unicode. */ +typedef struct RE_EncodingTable { + BOOL (*has_property)(RE_LocaleInfo* locale_info, RE_CODE property, Py_UCS4 + ch); + BOOL (*at_boundary)(RE_StatePtr state, Py_ssize_t text_pos); + BOOL (*at_word_start)(RE_StatePtr state, Py_ssize_t text_pos); + BOOL (*at_word_end)(RE_StatePtr state, Py_ssize_t text_pos); + BOOL (*at_default_boundary)(RE_StatePtr state, Py_ssize_t text_pos); + BOOL (*at_default_word_start)(RE_StatePtr state, Py_ssize_t text_pos); + BOOL (*at_default_word_end)(RE_StatePtr state, Py_ssize_t text_pos); + BOOL (*at_grapheme_boundary)(RE_StatePtr state, Py_ssize_t text_pos); + BOOL (*is_line_sep)(Py_UCS4 ch); + BOOL (*at_line_start)(RE_StatePtr state, Py_ssize_t text_pos); + BOOL (*at_line_end)(RE_StatePtr state, Py_ssize_t text_pos); + BOOL (*possible_turkic)(RE_LocaleInfo* locale_info, Py_UCS4 ch); + int (*all_cases)(RE_LocaleInfo* locale_info, Py_UCS4 ch, Py_UCS4* + codepoints); + Py_UCS4 (*simple_case_fold)(RE_LocaleInfo* locale_info, Py_UCS4 ch); + int (*full_case_fold)(RE_LocaleInfo* locale_info, Py_UCS4 ch, Py_UCS4* + folded); + int (*all_turkic_i)(RE_LocaleInfo* locale_info, Py_UCS4 ch, Py_UCS4* + cases); +} RE_EncodingTable; + +/* Position within the regex and text. */ +typedef struct RE_Position { + struct RE_Node* node; + Py_ssize_t text_pos; +} RE_Position; + +/* Info about a group's span. */ +typedef struct RE_GroupSpan { + Py_ssize_t start; + Py_ssize_t end; +} RE_GroupSpan; + +/* Storage for the next node. */ +typedef struct RE_NextNode { + struct RE_Node* node; + struct RE_Node* test; + struct RE_Node* match_next; + Py_ssize_t match_step; +} RE_NextNode; + +/* A pattern node. */ +typedef struct RE_Node { + RE_NextNode next_1; + union { + struct { + RE_NextNode next_2; + struct RE_Node* true_node; /* Used by a CONDITIONAL node. */ + } nonstring; + struct { + /* Used only if (node->status & RE_STATUS_STRING) is true. */ + Py_ssize_t* bad_character_offset; + Py_ssize_t* good_suffix_offset; + } string; + }; + Py_ssize_t step; + size_t value_count; + RE_CODE* values; + RE_STATUS_T status; + RE_UINT8 op; + BOOL match; +} RE_Node; + +/* Span of a guard (inclusive range). */ +typedef struct RE_GuardSpan { + Py_ssize_t low; + Py_ssize_t high; + BOOL protect; +} RE_GuardSpan; + +/* Spans guarded against further matching. */ +typedef struct RE_GuardList { + size_t capacity; + size_t count; + RE_GuardSpan* spans; + Py_ssize_t last_text_pos; + size_t last_low; +} RE_GuardList; + +/* Info about a group. */ +typedef struct RE_GroupData { + size_t capacity; + size_t count; + Py_ssize_t current; + RE_GroupSpan* captures; +} RE_GroupData; + +/* Info about a repeat. */ +typedef struct RE_RepeatData { + RE_GuardList body_guard_list; + RE_GuardList tail_guard_list; + size_t count; + Py_ssize_t start; + size_t capture_change; +} RE_RepeatData; + +/* Guards for fuzzy sections. */ +typedef struct RE_FuzzyGuards { + RE_GuardList body_guard_list; + RE_GuardList tail_guard_list; +} RE_FuzzyGuards; + +/* Info about a capture group. */ +typedef struct RE_GroupInfo { + Py_ssize_t end_index; + RE_Node* node; + BOOL referenced; + BOOL has_name; +} RE_GroupInfo; + +/* Info about a call_ref. */ +typedef struct RE_CallRefInfo { + RE_Node* node; + BOOL defined; + BOOL used; +} RE_CallRefInfo; + +/* Info about a repeat. */ +typedef struct RE_RepeatInfo { + RE_STATUS_T status; +} RE_RepeatInfo; + +/* Info about a string argument. */ +typedef struct RE_StringInfo { + Py_buffer view; /* View of the string if it's a buffer object. */ + void* characters; /* Pointer to the characters of the string. */ + Py_ssize_t length; /* Length of the string. */ + Py_ssize_t charsize; /* Size of the characters in the string. */ + BOOL is_unicode; /* Whether the string is Unicode. */ + BOOL should_release; /* Whether the buffer should be released. */ +} RE_StringInfo; + +/* Info about where the next match was found, starting from a certain search + * position. This is used when a pattern starts with a BRANCH. + */ +#define MAX_SEARCH_POSITIONS 7 + +/* Info about a search position. */ +typedef struct { + Py_ssize_t start_pos; + Py_ssize_t match_pos; +} RE_SearchPosition; + +typedef struct RE_FuzzyChange { + RE_UINT8 type; + Py_ssize_t pos; +} RE_FuzzyChange; + +typedef struct RE_FuzzyChangesList { + size_t capacity; + size_t count; + RE_FuzzyChange* items; +} RE_FuzzyChangesList; + +typedef struct RE_BestChangesList { + size_t capacity; + size_t count; + RE_FuzzyChangesList* lists; +} RE_BestChangesList; + +typedef struct RE_LookaroundStateData { + void* node; + Py_ssize_t slice_start; + Py_ssize_t slice_end; + Py_ssize_t text_pos; +} RE_LookaroundStateData; + +typedef struct RE_GroupStateData { + Py_ssize_t text_pos; + Py_ssize_t current; + size_t capture_change; + RE_CODE private_index; + RE_CODE public_index; +} RE_GroupStateData; + +typedef struct RE_MatchBodyTailStateData { + RE_Position position; + size_t count; + Py_ssize_t start; + size_t capture_change; + RE_CODE index; + Py_ssize_t text_pos; +} RE_MatchBodyTailStateData; + +typedef struct RE_BodyEndStateData { + size_t count; + Py_ssize_t start; + size_t capture_change; + RE_CODE index; +} RE_BodyEndStateData; + +typedef struct RE_RepeatStateData { + size_t count; + Py_ssize_t start; + size_t capture_change; + RE_CODE index; + Py_ssize_t text_pos; +} RE_RepeatStateData; + +typedef struct RE_RepeatOneStateData { + size_t count; + Py_ssize_t start; + void* node; + RE_CODE index; +} RE_RepeatOneStateData; + +/* A stack of bytes. */ +typedef struct ByteStack { + size_t capacity; + size_t count; + BYTE* storage; +} ByteStack; + +/* The state object used during matching. */ +typedef struct RE_State { + struct PatternObject* pattern; /* Parent PatternObject. */ + /* Info about the string being matched. */ + PyObject* string; + Py_buffer view; /* View of the string if it's a buffer object. */ + Py_ssize_t charsize; + void* text; + Py_ssize_t text_length; + /* The slice of the string being searched. */ + Py_ssize_t slice_start; + Py_ssize_t slice_end; + /* The hard limits of the string being searched. */ + Py_ssize_t text_start; + Py_ssize_t text_end; + /* Info about the capture groups. */ + RE_GroupData* groups; + Py_ssize_t lastindex; + Py_ssize_t lastgroup; + /* Info about the repeats. */ + RE_RepeatData* repeats; + Py_ssize_t search_anchor; /* Where the last match finished. */ + Py_ssize_t match_pos; /* The start position of the match. */ + Py_ssize_t text_pos; /* The current position of the match. */ + Py_ssize_t final_newline; /* The index of newline at end of string, or -1. */ + Py_ssize_t final_line_sep; /* The index of line separator at end of string, or -1. */ + /* Storage for backtrack info. */ + ByteStack sstack; /* The structure stack. */ + ByteStack bstack; /* The backtracking stack. */ + ByteStack pstack; /* The pruning stack. */ + /* Info about the best POSIX match (leftmost longest). */ + Py_ssize_t best_match_pos; + Py_ssize_t best_text_pos; + RE_GroupData* best_match_groups; + /* Miscellaneous. */ + Py_ssize_t min_width; /* The minimum width of the string to match (assuming it's not a fuzzy pattern). */ + RE_EncodingTable* encoding; /* The 'encoding' of the string being searched. */ + RE_LocaleInfo* locale_info; /* Info about the locale, if needed. */ + Py_UCS4 (*char_at)(void* text, Py_ssize_t pos); + void (*set_char_at)(void* text, Py_ssize_t pos, Py_UCS4 ch); + void* (*point_to)(void* text, Py_ssize_t pos); + PyThreadState* thread_state; /* The thread state after releasing the GIL. */ + PyThread_type_lock lock; /* A lock for accessing the state across threads. */ + size_t fuzzy_counts[RE_FUZZY_COUNT]; /* The counts for the current fuzzy matching. */ + RE_Node* fuzzy_node; /* The node of the current fuzzy matching. */ + size_t best_fuzzy_counts[RE_FUZZY_COUNT]; /* Best totals for fuzzy matching. */ + RE_FuzzyGuards* fuzzy_guards; /* The guards for a fuzzy match. */ + size_t total_errors; /* The total number of errors of a fuzzy match. */ + size_t max_errors; /* The maximum permitted number of errors. */ + size_t fewest_errors; /* The fewest errors so far of an enhanced fuzzy match. */ + /* The group call guards. */ + RE_GuardList* group_call_guard_list; + RE_FuzzyChangesList fuzzy_changes; + RE_SearchPosition search_positions[MAX_SEARCH_POSITIONS]; /* Where the search matches next. */ + size_t capture_change; /* Incremented every time a captive group changes. */ + Py_ssize_t req_pos; /* The position where the required string matched. */ + Py_ssize_t req_end; /* The end position where the required string matched. */ + Py_ssize_t timeout; /* The timeout in clock ticks. */ + clock_t start_time; /* The clock time when matching started. */ + int partial_side; /* The side that could truncate in a partial match. */ + /* Various flags. */ + RE_UINT16 iterations; /* The number of iterations the matching engine has performed since checking for KeyboardInterrupt. */ + BOOL is_unicode; /* Whether the string to be matched is Unicode. */ + BOOL should_release; /* Whether the buffer should be released. */ + BOOL overlapped; /* Whether the matches can be overlapped. */ + BOOL reverse; /* Whether it's a reverse pattern. */ + BOOL visible_captures; /* Whether the 'captures' method will be visible. */ + BOOL version_0; /* Whether to perform version_0 behaviour (same as re module). */ + BOOL must_advance; /* Whether the end of the match must advance past its start. */ + BOOL is_multithreaded; /* Whether to release the GIL while matching. */ + BOOL too_few_errors; /* Whether there were too few fuzzy errors. */ + BOOL match_all; /* Whether to match all of the string ('fullmatch'). */ + BOOL found_match; /* Whether a POSIX match has been found. */ + BOOL is_fuzzy; /* Whether the pattern is fuzzy. */ +} RE_State; + +/* The PatternObject created from a regular expression. */ +typedef struct PatternObject { + PyObject_HEAD + PyObject* pattern; /* Pattern source (or None). */ + Py_ssize_t flags; /* Flags used when compiling pattern source. */ + PyObject* packed_code_list; + PyObject* weakreflist; /* List of weak references */ + /* Nodes into which the regular expression is compiled. */ + RE_Node* start_node; + RE_Node* start_test; + size_t true_group_count; /* The true number of capture groups. */ + size_t public_group_count; /* The number of public capture groups. */ + size_t visible_capture_count; /* The number of capture groups that are visible (not hidden in (?(DEFINE)...). */ + size_t repeat_count; /* The number of repeats. */ + Py_ssize_t group_end_index; /* The number of group closures. */ + PyObject* groupindex; + PyObject* indexgroup; + PyObject* named_lists; + size_t named_lists_count; + PyObject** partial_named_lists[2]; + PyObject* named_list_indexes; + /* Storage for the pattern nodes. */ + size_t node_capacity; + size_t node_count; + RE_Node** node_list; + /* Info about the capture groups. */ + size_t group_info_capacity; + RE_GroupInfo* group_info; + /* Info about the call_refs. */ + size_t call_ref_info_capacity; + size_t call_ref_info_count; + RE_CallRefInfo* call_ref_info; + Py_ssize_t pattern_call_ref; + /* Info about the repeats. */ + size_t repeat_info_capacity; + RE_RepeatInfo* repeat_info; + Py_ssize_t min_width; /* The minimum width of the string to match (assuming it isn't a fuzzy pattern). */ + RE_EncodingTable* encoding; /* Encoding handlers. */ + RE_LocaleInfo* locale_info; /* Info about the locale, if needed. */ + RE_GroupData* groups_storage; /* Cached storage for group data. */ + RE_RepeatData* repeats_storage; /* Cached storage for repeats. */ + BYTE* stack_storage; /* Cached storage for the bstack. */ + size_t stack_capacity; /* The size of the cached storage for bstack. */ + size_t fuzzy_count; /* The number of fuzzy sections. */ + /* Additional info. */ + Py_ssize_t req_offset; /* The offset to the required string. */ + PyObject* required_chars; + Py_ssize_t req_flags; + RE_Node* req_string; /* The required string. */ + BOOL is_fuzzy; /* Whether it's a fuzzy pattern. */ + BOOL do_search_start; /* Whether to do an initial search. */ +} PatternObject; + +/* The MatchObject created when a match is found. */ +typedef struct MatchObject { + PyObject_HEAD + PyObject* string; /* Link to the target string or NULL if detached. */ + PyObject* substring; /* Link to (a substring of) the target string. */ + Py_ssize_t substring_offset; /* Offset into the target string. */ + PatternObject* pattern; /* Link to the regex (pattern) object. */ + Py_ssize_t pos; /* Start of current slice. */ + Py_ssize_t endpos; /* End of current slice. */ + Py_ssize_t match_start; /* Start of matched slice. */ + Py_ssize_t match_end; /* End of matched slice. */ + Py_ssize_t lastindex; /* Last group seen by the engine (-1 if none). */ + Py_ssize_t lastgroup; /* Last named group seen by the engine (-1 if none). */ + size_t group_count; /* The number of groups. */ + RE_GroupData* groups; /* The capture groups. */ + PyObject* regs; + size_t fuzzy_counts[RE_FUZZY_COUNT]; + RE_FuzzyChange* fuzzy_changes; + BOOL partial; /* Whether it's a partial match. */ +} MatchObject; + +/* The ScannerObject. */ +typedef struct ScannerObject { + PyObject_HEAD + PatternObject* pattern; + RE_State state; + int status; +} ScannerObject; + +/* The SplitterObject. */ +typedef struct SplitterObject { + PyObject_HEAD + PatternObject* pattern; + RE_State state; + Py_ssize_t maxsplit; + Py_ssize_t last_pos; + Py_ssize_t split_count; + Py_ssize_t index; + int status; +} SplitterObject; + +/* The CaptureObject. */ +typedef struct CaptureObject { + PyObject_HEAD + Py_ssize_t group_index; + MatchObject** match_indirect; +} CaptureObject; + +/* Info used when compiling a pattern to nodes. */ +typedef struct RE_CompileArgs { + RE_CODE* code; /* The start of the compiled pattern. */ + RE_CODE* end_code; /* The end of the compiled pattern. */ + PatternObject* pattern; /* The pattern object. */ + Py_ssize_t min_width; /* The minimum width of the string to match (assuming it isn't a fuzzy pattern). */ + RE_Node* start; /* The start node. */ + RE_Node* end; /* The end node. */ + size_t repeat_depth; /* The nesting depth of the repeat. */ + size_t visible_capture_count; /* The number of capture groups that are visible (not hidden in (?(DEFINE)...). */ + BOOL forward; /* Whether it's a forward (not reverse) pattern. */ + BOOL visible_captures; /* Whether all of the captures will be visible. */ + BOOL has_captures; /* Whether the pattern has capture groups. */ + BOOL is_fuzzy; /* Whether the pattern (or some part of it) is fuzzy. */ + BOOL within_fuzzy; /* Whether the subpattern is within a fuzzy section. */ + BOOL has_groups; /* Whether the subpattern contains captures. */ + BOOL has_repeats; /* Whether the subpattern contains repeats. */ + BOOL in_define; /* Whether we're in (?(DEFINE)...). */ + BOOL all_atomic; /* The sequence consists only of atomic items. */ +} RE_CompileArgs; + +/* The string slices which will be concatenated to make the result string of + * the 'sub' method. + * + * This allows us to avoid creating a list of slices if there of fewer than 2 + * of them. Empty strings aren't recorded, so if 'list' and 'item' are both + * NULL then the result is an empty string. + */ +typedef struct RE_JoinInfo { + PyObject* list; /* The list of slices if there are more than 2 of them. */ + PyObject* item; /* The slice if there is only 1 of them. */ + BOOL reversed; /* Whether the slices have been found in reverse order. */ + BOOL is_unicode; /* Whether the string is Unicode. */ +} RE_JoinInfo; + +/* Info about fuzzy matching. */ +typedef struct { + RE_Node* new_node; + Py_ssize_t new_text_pos; + Py_ssize_t limit; + Py_ssize_t new_string_pos; + int new_folded_pos; + int folded_len; + int new_gfolded_pos; + int new_group_pos; + RE_UINT8 fuzzy_type; + RE_INT8 step; + BOOL permit_insertion; +} RE_FuzzyData; + +typedef struct RE_BestEntry { + Py_ssize_t match_pos; + Py_ssize_t text_pos; +} RE_BestEntry; + +typedef struct RE_BestList { + size_t capacity; + size_t count; + RE_BestEntry* entries; +} RE_BestList; + +/* A stack of guard checks. */ +typedef struct RE_Check { + RE_Node* node; + RE_STATUS_T result; +} RE_Check; + +typedef struct RE_CheckStack { + size_t capacity; + size_t count; + RE_Check* items; +} RE_CheckStack; + +/* A stack of nodes. */ +typedef struct RE_NodeStack { + size_t capacity; + size_t count; + RE_Node** items; +} RE_NodeStack; + +/* Function types for getting info from a MatchObject. */ +typedef PyObject* (*RE_GetByIndexFunc)(MatchObject* self, Py_ssize_t index); + +/* Returns the magnitude of a 'Py_ssize_t' value. */ +Py_LOCAL_INLINE(Py_ssize_t) abs_ssize_t(Py_ssize_t x) { + return x >= 0 ? x : -x; +} + +/* Returns the minimum of 2 'Py_ssize_t' values. */ +Py_LOCAL_INLINE(Py_ssize_t) min_ssize_t(Py_ssize_t x, Py_ssize_t y) { + return x <= y ? x : y; +} + +/* Returns the maximum of 2 'Py_ssize_t' values. */ +Py_LOCAL_INLINE(Py_ssize_t) max_ssize_t(Py_ssize_t x, Py_ssize_t y) { + return x >= y ? x : y; +} + +/* Returns the minimum of 2 'size_t' values. */ +Py_LOCAL_INLINE(size_t) min_size_t(size_t x, size_t y) { + return x <= y ? x : y; +} + +/* Returns the 'maximum' of 2 RE_STATUS_T values. */ +Py_LOCAL_INLINE(RE_STATUS_T) max_status_2(RE_STATUS_T x, RE_STATUS_T y) { + return x >= y ? x : y; +} + +/* Returns the 'maximum' of 3 RE_STATUS_T values. */ +Py_LOCAL_INLINE(RE_STATUS_T) max_status_3(RE_STATUS_T x, RE_STATUS_T y, + RE_STATUS_T z) { + return max_status_2(x, max_status_2(y, z)); +} + +/* Returns the 'maximum' of 4 RE_STATUS_T values. */ +Py_LOCAL_INLINE(RE_STATUS_T) max_status_4(RE_STATUS_T w, RE_STATUS_T x, + RE_STATUS_T y, RE_STATUS_T z) { + return max_status_2(max_status_2(w, x), max_status_2(y, z)); +} + +/* Gets a character at a position assuming 1 byte per character. */ +static Py_UCS4 bytes1_char_at(void* text, Py_ssize_t pos) { + return *((Py_UCS1*)text + pos); +} + +/* Sets a character at a position assuming 1 byte per character. */ +static void bytes1_set_char_at(void* text, Py_ssize_t pos, Py_UCS4 ch) { + *((Py_UCS1*)text + pos) = (Py_UCS1)ch; +} + +/* Gets a pointer to a position assuming 1 byte per character. */ +static void* bytes1_point_to(void* text, Py_ssize_t pos) { + return (Py_UCS1*)text + pos; +} + +/* Gets a character at a position assuming 2 bytes per character. */ +static Py_UCS4 bytes2_char_at(void* text, Py_ssize_t pos) { + return *((Py_UCS2*)text + pos); +} + +/* Sets a character at a position assuming 2 bytes per character. */ +static void bytes2_set_char_at(void* text, Py_ssize_t pos, Py_UCS4 ch) { + *((Py_UCS2*)text + pos) = (Py_UCS2)ch; +} + +/* Gets a pointer to a position assuming 2 bytes per character. */ +static void* bytes2_point_to(void* text, Py_ssize_t pos) { + return (Py_UCS2*)text + pos; +} + +/* Gets a character at a position assuming 4 bytes per character. */ +static Py_UCS4 bytes4_char_at(void* text, Py_ssize_t pos) { + return *((Py_UCS4*)text + pos); +} + +/* Sets a character at a position assuming 4 bytes per character. */ +static void bytes4_set_char_at(void* text, Py_ssize_t pos, Py_UCS4 ch) { + *((Py_UCS4*)text + pos) = (Py_UCS4)ch; +} + +/* Gets a pointer to a position assuming 4 bytes per character. */ +static void* bytes4_point_to(void* text, Py_ssize_t pos) { + return (Py_UCS4*)text + pos; +} + +/* Default for whether a position is on a word boundary. */ +static BOOL at_boundary_always(RE_State* state, Py_ssize_t text_pos) { + return TRUE; +} + +/* Converts a BOOL to success/failure. */ +Py_LOCAL_INLINE(int) bool_as_status(BOOL value) { + return value ? RE_ERROR_SUCCESS : RE_ERROR_FAILURE; +} + +/* ASCII-specific. */ + +Py_LOCAL_INLINE(BOOL) unicode_has_property(RE_CODE property, Py_UCS4 ch); + +/* Checks whether a character has a property. */ +Py_LOCAL_INLINE(BOOL) ascii_has_property(RE_CODE property, Py_UCS4 ch) { + if (ch > RE_ASCII_MAX) { + /* Outside the ASCII range. */ + RE_UINT32 value; + + value = property & 0xFFFF; + + return value == 0; + } + + return unicode_has_property(property, ch); +} + +/* Checks whether a character has a property, ignoring case. */ +Py_LOCAL_INLINE(BOOL) ascii_has_property_ign(RE_CODE property, Py_UCS4 ch) { + RE_UINT32 prop; + + prop = property >> 16; + + /* We are working with ASCII. */ + if (property == RE_PROP_GC_LU || property == RE_PROP_GC_LL || property == + RE_PROP_GC_LT) { + RE_UINT32 value; + + value = re_get_general_category(ch); + + return value == RE_PROP_LU || value == RE_PROP_LL || value == + RE_PROP_LT; + } else if (prop == RE_PROP_UPPERCASE || prop == RE_PROP_LOWERCASE) + return (BOOL)re_get_cased(ch); + + /* The property is case-insensitive. */ + return ascii_has_property(property, ch); +} + +/* Wrapper for calling 'ascii_has_property' via a pointer. */ +static BOOL ascii_has_property_wrapper(RE_LocaleInfo* locale_info, RE_CODE + property, Py_UCS4 ch) { + return ascii_has_property(property, ch); +} + +/* Checks whether there's a word character to the left. */ +Py_LOCAL_INLINE(BOOL) ascii_word_left(RE_State* state, Py_ssize_t text_pos) { + return text_pos > state->text_start && ascii_has_property(RE_PROP_WORD, + state->char_at(state->text, text_pos - 1)); +} + +/* Checks whether there's a word character to the right. */ +Py_LOCAL_INLINE(BOOL) ascii_word_right(RE_State* state, Py_ssize_t text_pos) { + return text_pos < state->text_end && ascii_has_property(RE_PROP_WORD, + state->char_at(state->text, text_pos)); +} + +/* Checks whether a position is on a word boundary. */ +static BOOL ascii_at_boundary(RE_State* state, Py_ssize_t text_pos) { + BOOL left; + BOOL right; + + left = ascii_word_left(state, text_pos); + right = ascii_word_right(state, text_pos); + + return left != right; +} + +/* Checks whether a position is at the start of a word. */ +static BOOL ascii_at_word_start(RE_State* state, Py_ssize_t text_pos) { + BOOL left; + BOOL right; + + left = ascii_word_left(state, text_pos); + right = ascii_word_right(state, text_pos); + + return !left && right; +} + +/* Checks whether a position is at the end of a word. */ +static BOOL ascii_at_word_end(RE_State* state, Py_ssize_t text_pos) { + BOOL left; + BOOL right; + + left = ascii_word_left(state, text_pos); + right = ascii_word_right(state, text_pos); + + return left && !right; +} + +/* Checks whether a character is a line separator. */ +static BOOL ascii_is_line_sep(Py_UCS4 ch) { + return 0x0A <= ch && ch <= 0x0D; +} + +/* Checks whether a position is at the start of a line. */ +static BOOL ascii_at_line_start(RE_State* state, Py_ssize_t text_pos) { + Py_UCS4 ch; + + if (text_pos <= state->text_start) + return TRUE; + + ch = state->char_at(state->text, text_pos - 1); + + if (ch == 0x0D) { + if (text_pos >= state->text_end) + return TRUE; + + /* No line break inside CRLF. */ + return state->char_at(state->text, text_pos) != 0x0A; + } + + return 0x0A <= ch && ch <= 0x0D; +} + +/* Checks whether a position is at the end of a line. */ +static BOOL ascii_at_line_end(RE_State* state, Py_ssize_t text_pos) { + Py_UCS4 ch; + + if (text_pos >= state->text_end) + return TRUE; + + ch = state->char_at(state->text, text_pos); + + if (ch == 0x0A) { + if (text_pos <= state->text_start) + return TRUE; + + /* No line break inside CRLF. */ + return state->char_at(state->text, text_pos - 1) != 0x0D; + } + + return 0x0A <= ch && ch <= 0x0D; +} + +/* Checks whether a character could be Turkic (variants of I/i). For ASCII, it + * won't be. + */ +static BOOL ascii_possible_turkic(RE_LocaleInfo* locale_info, Py_UCS4 ch) { + return FALSE; +} + +/* Gets all the cases of a character. */ +static int ascii_all_cases(RE_LocaleInfo* locale_info, Py_UCS4 ch, Py_UCS4* + codepoints) { + int count; + + count = 0; + + codepoints[count++] = ch; + + if (('A' <= ch && ch <= 'Z') || ('a' <= ch && ch <= 'z')) + /* It's a letter, so add the other case. */ + codepoints[count++] = ch ^ 0x20; + + return count; +} + +/* Returns a character with its case folded. */ +static Py_UCS4 ascii_simple_case_fold(RE_LocaleInfo* locale_info, Py_UCS4 ch) { + if ('A' <= ch && ch <= 'Z') + /* Uppercase folds to lowercase. */ + return ch ^ 0x20; + + return ch; +} + +/* Returns a character with its case folded. */ +static int ascii_full_case_fold(RE_LocaleInfo* locale_info, Py_UCS4 ch, + Py_UCS4* folded) { + if ('A' <= ch && ch <= 'Z') + /* Uppercase folds to lowercase. */ + folded[0] = ch ^ 0x20; + else + folded[0] = ch; + + return 1; +} + +/* Gets all the case variants of Turkic 'I'. The given character will be listed + * first. + */ +static int ascii_all_turkic_i(RE_LocaleInfo* locale_info, Py_UCS4 ch, Py_UCS4* + cases) { + int count; + + count = 0; + + cases[count++] = ch; + + if (ch != 'I') + cases[count++] = 'I'; + + if (ch != 'i') + cases[count++] = 'i'; + + return count; +} + +/* The handlers for ASCII characters. */ +static RE_EncodingTable ascii_encoding = { + ascii_has_property_wrapper, + ascii_at_boundary, + ascii_at_word_start, + ascii_at_word_end, + ascii_at_boundary, /* No special "default word boundary" for ASCII. */ + ascii_at_word_start, /* No special "default start of word" for ASCII. */ + ascii_at_word_end, /* No special "default end of a word" for ASCII. */ + at_boundary_always, /* No special "grapheme boundary" for ASCII. */ + ascii_is_line_sep, + ascii_at_line_start, + ascii_at_line_end, + ascii_possible_turkic, + ascii_all_cases, + ascii_simple_case_fold, + ascii_full_case_fold, + ascii_all_turkic_i, +}; + +/* Locale-specific. */ + +/* Checks whether a character has the 'alnum' property in the given locale. */ +Py_LOCAL_INLINE(BOOL) locale_isalnum(RE_LocaleInfo* locale_info, Py_UCS4 ch) { + return ch <= RE_LOCALE_MAX && (locale_info->properties[ch] & + RE_LOCALE_ALNUM) != 0; +} + +/* Checks whether a character has the 'alpha' property in the given locale. */ +Py_LOCAL_INLINE(BOOL) locale_isalpha(RE_LocaleInfo* locale_info, Py_UCS4 ch) { + return ch <= RE_LOCALE_MAX && (locale_info->properties[ch] & + RE_LOCALE_ALPHA) != 0; +} + +/* Checks whether a character has the 'cntrl' property in the given locale. */ +Py_LOCAL_INLINE(BOOL) locale_iscntrl(RE_LocaleInfo* locale_info, Py_UCS4 ch) { + return ch <= RE_LOCALE_MAX && (locale_info->properties[ch] & + RE_LOCALE_CNTRL) != 0; +} + +/* Checks whether a character has the 'digit' property in the given locale. */ +Py_LOCAL_INLINE(BOOL) locale_isdigit(RE_LocaleInfo* locale_info, Py_UCS4 ch) { + return ch <= RE_LOCALE_MAX && (locale_info->properties[ch] & + RE_LOCALE_DIGIT) != 0; +} + +/* Checks whether a character has the 'graph' property in the given locale. */ +Py_LOCAL_INLINE(BOOL) locale_isgraph(RE_LocaleInfo* locale_info, Py_UCS4 ch) { + return ch <= RE_LOCALE_MAX && (locale_info->properties[ch] & + RE_LOCALE_GRAPH) != 0; +} + +/* Checks whether a character has the 'lower' property in the given locale. */ +Py_LOCAL_INLINE(BOOL) locale_islower(RE_LocaleInfo* locale_info, Py_UCS4 ch) { + return ch <= RE_LOCALE_MAX && (locale_info->properties[ch] & + RE_LOCALE_LOWER) != 0; +} + +/* Checks whether a character has the 'print' property in the given locale. */ +Py_LOCAL_INLINE(BOOL) locale_isprint(RE_LocaleInfo* locale_info, Py_UCS4 ch) { + return ch <= RE_LOCALE_MAX && (locale_info->properties[ch] & + RE_LOCALE_PRINT) != 0; +} + +/* Checks whether a character has the 'punct' property in the given locale. */ +Py_LOCAL_INLINE(BOOL) locale_ispunct(RE_LocaleInfo* locale_info, Py_UCS4 ch) { + return ch <= RE_LOCALE_MAX && (locale_info->properties[ch] & + RE_LOCALE_PUNCT) != 0; +} + +/* Checks whether a character has the 'space' property in the given locale. */ +Py_LOCAL_INLINE(BOOL) locale_isspace(RE_LocaleInfo* locale_info, Py_UCS4 ch) { + return ch <= RE_LOCALE_MAX && (locale_info->properties[ch] & + RE_LOCALE_SPACE) != 0; +} + +/* Checks whether a character has the 'upper' property in the given locale. */ +Py_LOCAL_INLINE(BOOL) locale_isupper(RE_LocaleInfo* locale_info, Py_UCS4 ch) { + return ch <= RE_LOCALE_MAX && (locale_info->properties[ch] & + RE_LOCALE_UPPER) != 0; +} + +/* Converts a character to lowercase in the given locale. */ +Py_LOCAL_INLINE(Py_UCS4) locale_tolower(RE_LocaleInfo* locale_info, Py_UCS4 ch) + { + return ch <= RE_LOCALE_MAX ? locale_info->lowercase[ch] : ch; +} + +/* Converts a character to uppercase in the given locale. */ +Py_LOCAL_INLINE(Py_UCS4) locale_toupper(RE_LocaleInfo* locale_info, Py_UCS4 ch) + { + return ch <= RE_LOCALE_MAX ? locale_info->uppercase[ch] : ch; +} + +/* Checks whether a character has a property. */ +Py_LOCAL_INLINE(BOOL) locale_has_property(RE_LocaleInfo* locale_info, RE_CODE + property, Py_UCS4 ch) { + RE_UINT32 value; + RE_UINT32 v; + + value = property & 0xFFFF; + + if (ch > RE_LOCALE_MAX) + /* Outside the locale range. */ + return value == 0; + + switch (property >> 16) { + case RE_PROP_ALNUM >> 16: + v = locale_isalnum(locale_info, ch) != 0; + break; + case RE_PROP_ALPHA >> 16: + v = locale_isalpha(locale_info, ch) != 0; + break; + case RE_PROP_ANY >> 16: + v = 1; + break; + case RE_PROP_ASCII >> 16: + v = ch <= RE_ASCII_MAX; + break; + case RE_PROP_BLANK >> 16: + v = ch == '\t' || ch == ' '; + break; + case RE_PROP_GC: + switch (property) { + case RE_PROP_ASSIGNED: + v = ch <= RE_LOCALE_MAX; + break; + case RE_PROP_CASEDLETTER: + v = locale_isalpha(locale_info, ch) ? value : 0xFFFF; + break; + case RE_PROP_CNTRL: + v = locale_iscntrl(locale_info, ch) ? value : 0xFFFF; + break; + case RE_PROP_DIGIT: + v = locale_isdigit(locale_info, ch) ? value : 0xFFFF; + break; + case RE_PROP_GC_CN: + v = ch > RE_LOCALE_MAX; + break; + case RE_PROP_GC_LL: + v = locale_islower(locale_info, ch) ? value : 0xFFFF; + break; + case RE_PROP_GC_LU: + v = locale_isupper(locale_info, ch) ? value : 0xFFFF; + break; + case RE_PROP_GC_P: + v = locale_ispunct(locale_info, ch) ? value : 0xFFFF; + break; + default: + v = 0xFFFF; + break; + } + break; + case RE_PROP_GRAPH >> 16: + v = locale_isgraph(locale_info, ch) != 0; + break; + case RE_PROP_LOWER >> 16: + v = locale_islower(locale_info, ch) != 0; + break; + case RE_PROP_POSIX_ALNUM >> 16: + v = re_get_posix_alnum(ch) != 0; + break; + case RE_PROP_POSIX_DIGIT >> 16: + v = re_get_posix_digit(ch) != 0; + break; + case RE_PROP_POSIX_PUNCT >> 16: + v = re_get_posix_punct(ch) != 0; + break; + case RE_PROP_POSIX_XDIGIT >> 16: + v = re_get_posix_xdigit(ch) != 0; + break; + case RE_PROP_PRINT >> 16: + v = locale_isprint(locale_info, ch) != 0; + break; + case RE_PROP_SPACE >> 16: + v = locale_isspace(locale_info, ch) != 0; + break; + case RE_PROP_UPPER >> 16: + v = locale_isupper(locale_info, ch) != 0; + break; + case RE_PROP_WORD >> 16: + v = ch == '_' || locale_isalnum(locale_info, ch) != 0; + break; + case RE_PROP_XDIGIT >> 16: + v = re_get_hex_digit(ch) != 0; + break; + default: + v = 0; + break; + } + + return v == value; +} + +/* Checks whether a character has a property, ignoring case. */ +Py_LOCAL_INLINE(BOOL) locale_has_property_ign(RE_LocaleInfo* locale_info, + RE_CODE property, Py_UCS4 ch) { + RE_UINT32 prop; + + prop = property >> 16; + + if (property == RE_PROP_GC_LU || property == RE_PROP_GC_LL || property == + RE_PROP_GC_LT) + return locale_isupper(locale_info, ch) || locale_islower(locale_info, + ch); + else if (prop == RE_PROP_UPPERCASE || prop == RE_PROP_LOWERCASE) + return locale_isupper(locale_info, ch) || locale_islower(locale_info, + ch); + + /* The property is case-insensitive. */ + return locale_has_property(locale_info, property, ch); +} + +/* Wrapper for calling 'locale_has_property' via a pointer. */ +static BOOL locale_has_property_wrapper(RE_LocaleInfo* locale_info, RE_CODE + property, Py_UCS4 ch) { + return locale_has_property(locale_info, property, ch); +} + +/* Checks whether there's a word character to the left. */ +Py_LOCAL_INLINE(BOOL) locale_word_left(RE_State* state, Py_ssize_t text_pos) { + return text_pos > state->text_start && locale_has_property(state->locale_info, + RE_PROP_WORD, state->char_at(state->text, text_pos - 1)); +} + +/* Checks whether there's a word character to the right. */ +Py_LOCAL_INLINE(BOOL) locale_word_right(RE_State* state, Py_ssize_t text_pos) { + return text_pos < state->text_end && + locale_has_property(state->locale_info, RE_PROP_WORD, + state->char_at(state->text, text_pos)); +} + +/* Checks whether a position is on a word boundary. */ +static BOOL locale_at_boundary(RE_State* state, Py_ssize_t text_pos) { + BOOL left; + BOOL right; + + left = locale_word_left(state, text_pos); + right = locale_word_right(state, text_pos); + + return left != right; +} + +/* Checks whether a position is at the start of a word. */ +static BOOL locale_at_word_start(RE_State* state, Py_ssize_t text_pos) { + BOOL left; + BOOL right; + + left = locale_word_left(state, text_pos); + right = locale_word_right(state, text_pos); + + return !left && right; +} + +/* Checks whether a position is at the end of a word. */ +static BOOL locale_at_word_end(RE_State* state, Py_ssize_t text_pos) { + BOOL left; + BOOL right; + + left = locale_word_left(state, text_pos); + right = locale_word_right(state, text_pos); + + return left && !right; +} + +/* Checks whether a character could be Turkic (variants of I/i). */ +static BOOL locale_possible_turkic(RE_LocaleInfo* locale_info, Py_UCS4 ch) { + return locale_toupper(locale_info, ch) == 'I' || + locale_tolower(locale_info, ch) == 'i'; +} + +/* Gets all the cases of a character. */ +static int locale_all_cases(RE_LocaleInfo* locale_info, Py_UCS4 ch, Py_UCS4* + codepoints) { + int count; + Py_UCS4 other; + + count = 0; + + codepoints[count++] = ch; + + other = locale_toupper(locale_info, ch); + if (other != ch) + codepoints[count++] = other; + + other = locale_tolower(locale_info, ch); + if (other != ch) + codepoints[count++] = other; + + return count; +} + +/* Returns a character with its case folded. */ +static Py_UCS4 locale_simple_case_fold(RE_LocaleInfo* locale_info, Py_UCS4 ch) + { + return locale_tolower(locale_info, ch); +} + +/* Returns a character with its case folded. */ +static int locale_full_case_fold(RE_LocaleInfo* locale_info, Py_UCS4 ch, + Py_UCS4* folded) { + folded[0] = locale_tolower(locale_info, ch); + + return 1; +} + +/* Gets all the case variants of Turkic 'I'. The given character will be listed + * first. + */ +static int locale_all_turkic_i(RE_LocaleInfo* locale_info, Py_UCS4 ch, Py_UCS4* + cases) { + int count; + Py_UCS4 other; + + count = 0; + + cases[count++] = ch; + + if (ch != 'I') + cases[count++] = 'I'; + + if (ch != 'i') + cases[count++] = 'i'; + + /* Uppercase 'i' will be either dotted (Turkic) or dotless (non-Turkic). */ + other = locale_toupper(locale_info, 'i'); + if (other != ch && other != 'I') + cases[count++] = other; + + /* Lowercase 'I' will be either dotless (Turkic) or dotted (non-Turkic). */ + other = locale_tolower(locale_info, 'I'); + if (other != ch && other != 'i') + cases[count++] = other; + + return count; +} + +/* The handlers for locale characters. */ +static RE_EncodingTable locale_encoding = { + locale_has_property_wrapper, + locale_at_boundary, + locale_at_word_start, + locale_at_word_end, + locale_at_boundary, /* No special "default word boundary" for locale. */ + locale_at_word_start, /* No special "default start of a word" for locale. */ + locale_at_word_end, /* No special "default end of a word" for locale. */ + at_boundary_always, /* No special "grapheme boundary" for locale. */ + ascii_is_line_sep, /* Assume locale line separators are same as ASCII. */ + ascii_at_line_start, /* Assume locale line separators are same as ASCII. */ + ascii_at_line_end, /* Assume locale line separators are same as ASCII. */ + locale_possible_turkic, + locale_all_cases, + locale_simple_case_fold, + locale_full_case_fold, + locale_all_turkic_i, +}; + +/* Unicode-specific. */ + +/* Checks whether a Unicode character has a property. */ +Py_LOCAL_INLINE(BOOL) unicode_has_property(RE_CODE property, Py_UCS4 ch) { + RE_UINT32 prop; + RE_UINT32 value; + RE_UINT32 v; + + prop = property >> 16; + if (prop >= sizeof(re_get_property) / sizeof(re_get_property[0])) + return FALSE; + + value = property & 0xFFFF; + + if (prop == RE_PROP_SCX) { + int count; + RE_UINT8 scripts[RE_MAX_SCX]; + int i; + + count = re_get_script_extensions(ch, scripts); + + for (i = 0; i < count; i++) { + if (scripts[i] == value) + return TRUE; + } + + return FALSE; + } + + v = re_get_property[prop](ch); + + if (v == value) + return TRUE; + + if (prop == RE_PROP_GC) { + switch (value) { + case RE_PROP_ASSIGNED: + return v != RE_PROP_CN; + case RE_PROP_C: + return (RE_PROP_C_MASK & (1 << v)) != 0; + case RE_PROP_CASEDLETTER: + return v == RE_PROP_LU || v == RE_PROP_LL || v == RE_PROP_LT; + case RE_PROP_L: + return (RE_PROP_L_MASK & (1 << v)) != 0; + case RE_PROP_M: + return (RE_PROP_M_MASK & (1 << v)) != 0; + case RE_PROP_N: + return (RE_PROP_N_MASK & (1 << v)) != 0; + case RE_PROP_P: + return (RE_PROP_P_MASK & (1 << v)) != 0; + case RE_PROP_S: + return (RE_PROP_S_MASK & (1 << v)) != 0; + case RE_PROP_Z: + return (RE_PROP_Z_MASK & (1 << v)) != 0; + } + } + + return FALSE; +} + +/* Checks whether a character has a property, ignoring case. */ +Py_LOCAL_INLINE(BOOL) unicode_has_property_ign(RE_CODE property, Py_UCS4 ch) { + RE_UINT32 prop; + + prop = property >> 16; + + if (property == RE_PROP_GC_LU || property == RE_PROP_GC_LL || property == + RE_PROP_GC_LT) { + RE_UINT32 value; + + value = re_get_general_category(ch); + + return value == RE_PROP_LU || value == RE_PROP_LL || value == + RE_PROP_LT; + } else if (prop == RE_PROP_UPPERCASE || prop == RE_PROP_LOWERCASE) + return (BOOL)re_get_cased(ch); + + /* The property is case-insensitive. */ + return unicode_has_property(property, ch); +} + +/* Wrapper for calling 'unicode_has_property' via a pointer. */ +static BOOL unicode_has_property_wrapper(RE_LocaleInfo* locale_info, RE_CODE + property, Py_UCS4 ch) { + return unicode_has_property(property, ch); +} + +/* Checks whether there's a word character to the left. */ +Py_LOCAL_INLINE(BOOL) unicode_word_left(RE_State* state, Py_ssize_t text_pos) { + return text_pos > state->text_start && unicode_has_property(RE_PROP_WORD, + state->char_at(state->text, text_pos - 1)); +} + +/* Checks whether there's a word character to the right. */ +Py_LOCAL_INLINE(BOOL) unicode_word_right(RE_State* state, Py_ssize_t text_pos) + { + return text_pos < state->text_end && unicode_has_property(RE_PROP_WORD, + state->char_at(state->text, text_pos)); +} + +/* Checks whether a position is on a word boundary. */ +static BOOL unicode_at_boundary(RE_State* state, Py_ssize_t text_pos) { + BOOL left; + BOOL right; + + left = unicode_word_left(state, text_pos); + right = unicode_word_right(state, text_pos); + + return left != right; +} + +/* Checks whether a position is at the start of a word. */ +static BOOL unicode_at_word_start(RE_State* state, Py_ssize_t text_pos) { + BOOL left; + BOOL right; + + left = unicode_word_left(state, text_pos); + right = unicode_word_right(state, text_pos); + + return !left && right; +} + +/* Checks whether a position is at the end of a word. */ +static BOOL unicode_at_word_end(RE_State* state, Py_ssize_t text_pos) { + BOOL left; + BOOL right; + + left = unicode_word_left(state, text_pos); + right = unicode_word_right(state, text_pos); + + return left && !right; +} + +/* Checks whether a character is a Unicode vowel. + * + * Only a limited number are treated as vowels. + */ +Py_LOCAL_INLINE(BOOL) is_unicode_vowel(Py_UCS4 ch) { + switch (Py_UNICODE_TOLOWER(ch)) { + case 'a': case 0xE0: case 0xE1: case 0xE2: + case 'e': case 0xE8: case 0xE9: case 0xEA: + case 'i': case 0xEC: case 0xED: case 0xEE: + case 'o': case 0xF2: case 0xF3: case 0xF4: + case 'u': case 0xF9: case 0xFA: case 0xFB: + return TRUE; + default: + return FALSE; + } +} + +/* Checks whether a character is a Unicode apostrophe. + * + * This could be U+0027 (APOSTROPHE) or U+2019 (RIGHT SINGLE QUOTATION MARK / + * curly apostrophe). + */ +static BOOL is_unicode_apostrophe(Py_UCS4 ch) { + return ch == 0x27 || ch == 0x2019; +} + +Py_LOCAL_INLINE(BOOL) IS_AHLETTER(RE_UINT32 v) { + return v == RE_WBREAK_ALETTER || v == RE_WBREAK_HEBREWLETTER; +} + +Py_LOCAL_INLINE(BOOL) IS_MIDNUMLETQ(RE_UINT32 v) { + return v == RE_WBREAK_MIDNUMLET || v == RE_WBREAK_SINGLEQUOTE; +} + +/* Checks whether a position is on a default word boundary. + * + * The rules are defined here: + * https://www.unicode.org/reports/tr29/#Default_Word_Boundaries + */ +static BOOL unicode_at_default_boundary(RE_State* state, Py_ssize_t text_pos) { + Py_UCS4 (*char_at)(void* text, Py_ssize_t pos); + Py_ssize_t left_pos; + Py_ssize_t right_pos; + Py_UCS4 left_char; + Py_UCS4 right_char; + RE_UINT32 left_prop; + RE_UINT32 right_prop; + Py_ssize_t pos; + + /* Break at the start and end of text, unless the text is empty. */ + /* WB1 and WB2 */ + if (text_pos <= state->text_start || text_pos >= state->text_end) + return state->text_end > state->text_start; + + /* In this function, left_pos is inclusive, i.e. it's the index of the + * character. + */ + char_at = state->char_at; + + left_pos = text_pos - 1; + right_pos = text_pos; + left_char = char_at(state->text, left_pos); + right_char = char_at(state->text, right_pos); + + /* Do not break within CRLF. */ + /* WB3 */ + left_prop = re_get_word_break(left_char); + right_prop = re_get_word_break(right_char); + + if (left_prop == RE_WBREAK_CR && right_prop == RE_WBREAK_LF) + return FALSE; + + /* Otherwise break before and after Newlines (including CR and LF) */ + /* WB3a */ + if (left_prop == RE_WBREAK_NEWLINE || left_prop == RE_WBREAK_CR || + left_prop == RE_WBREAK_LF) + return TRUE; + + /* WB3b */ + if (right_prop == RE_WBREAK_NEWLINE || right_prop == RE_WBREAK_CR || + right_prop == RE_WBREAK_LF) + return TRUE; + + /* Do not break within emoji zwj sequences. */ + /* WB3c */ + if (left_prop == RE_WBREAK_ZWJ && re_get_extended_pictographic(right_char) + != 0) + return FALSE; + + /* Keep horizontal whitespace together. */ + /* WB3d */ + if (left_prop == RE_WBREAK_WSEGSPACE && right_prop == RE_WBREAK_WSEGSPACE) + return FALSE; + + /* Ignore Format and Extend characters, except after sot, CR, LF, and + * Newline. This also has the effect of: Any x (Format || Extend || ZWJ) + */ + /* WB4 */ + if (right_prop == RE_WBREAK_EXTEND || right_prop == RE_WBREAK_FORMAT || + right_prop == RE_WBREAK_ZWJ) + return FALSE; + + while (left_prop == RE_WBREAK_EXTEND || left_prop == RE_WBREAK_FORMAT || + left_prop == RE_WBREAK_ZWJ) { + if (left_pos <= state->text_start) + return FALSE; + --left_pos; + left_char = char_at(state->text, left_pos); + left_prop = re_get_word_break(left_char); + } + + /* Do not break between most letters. */ + /* WB5 */ + if (IS_AHLETTER(left_prop) && IS_AHLETTER(right_prop)) + return FALSE; + + /* Break between apostrophe and vowels (French, Italian). */ + /* WB5a */ + if (is_unicode_apostrophe(left_char) && is_unicode_vowel(right_char)) + return FALSE; + + /* Do not break letters across certain punctuation. */ + /* WB6 */ + if (right_pos + 1 < state->text_end) { + Py_UCS4 right_right_char; + RE_UINT32 right_right_prop; + + right_right_char = char_at(state->text, right_pos + 1); + right_right_prop = re_get_word_break(right_right_char); + + if (IS_AHLETTER(left_prop) && (right_prop == RE_WBREAK_MIDLETTER || + IS_MIDNUMLETQ(right_prop)) && IS_AHLETTER(right_right_prop)) + return FALSE; + } + + /* WB7 */ + if (left_pos - 1 >= state->text_start) { + Py_UCS4 left_left_char; + RE_UINT32 left_left_prop; + + left_left_char = char_at(state->text, left_pos - 1); + left_left_prop = re_get_word_break(left_left_char); + + if (IS_AHLETTER(left_left_prop) && (left_prop == RE_WBREAK_MIDLETTER || + IS_MIDNUMLETQ(left_prop)) && IS_AHLETTER(right_prop)) + return FALSE; + } + + /* WB7a */ + if (left_prop == RE_WBREAK_HEBREWLETTER && right_prop == + RE_WBREAK_SINGLEQUOTE) + return FALSE; + + /* WB7b */ + if (right_pos + 1 < state->text_end) { + Py_UCS4 right_right_char; + RE_UINT32 right_right_prop; + + right_right_char = char_at(state->text, right_pos + 1); + right_right_prop = re_get_word_break(right_right_char); + + if (left_prop == RE_WBREAK_HEBREWLETTER && right_prop == + RE_WBREAK_DOUBLEQUOTE && right_right_prop == RE_WBREAK_HEBREWLETTER) + return FALSE; + } + + /* WB7c */ + if (left_pos - 1 >= state->text_start) { + Py_UCS4 left_left_char; + RE_UINT32 left_left_prop; + + left_left_char = char_at(state->text, left_pos - 1); + left_left_prop = re_get_word_break(left_left_char); + + if (left_left_prop == RE_WBREAK_HEBREWLETTER && left_prop == + RE_WBREAK_DOUBLEQUOTE && right_prop == RE_WBREAK_HEBREWLETTER) + return FALSE; + } + + /* Do not break within sequences of digits, or digits adjacent to letters + * ("3a", or "A3"). + */ + /* WB8 */ + if (left_prop == RE_WBREAK_NUMERIC && right_prop == RE_WBREAK_NUMERIC) + return FALSE; + + /* WB9 */ + if (IS_AHLETTER(left_prop) && right_prop == RE_WBREAK_NUMERIC) + return FALSE; + + /* WB10 */ + if (left_prop == RE_WBREAK_NUMERIC && IS_AHLETTER(right_prop)) + return FALSE; + + /* Do not break within sequences, such as "3.2" or "3,456.789". */ + /* WB11 */ + if (left_pos - 1 >= state->text_start) { + Py_UCS4 left_left_char; + RE_UINT32 left_left_prop; + + left_left_char = char_at(state->text, left_pos - 1); + left_left_prop = re_get_word_break(left_left_char); + + if (left_left_prop == RE_WBREAK_NUMERIC && (left_prop == + RE_WBREAK_MIDNUM || IS_MIDNUMLETQ(left_prop)) && right_prop == + RE_WBREAK_NUMERIC) + return FALSE; + } + + /* WB12 */ + if (right_pos + 1 < state->text_end) { + Py_UCS4 right_right_char; + RE_UINT32 right_right_prop; + + right_right_char = char_at(state->text, right_pos + 1); + right_right_prop = re_get_word_break(right_right_char); + + if (left_prop == RE_WBREAK_NUMERIC && (right_prop == RE_WBREAK_MIDNUM + || IS_MIDNUMLETQ(right_prop)) && right_right_prop == + RE_WBREAK_NUMERIC) + return FALSE; + } + + /* Do not break between Katakana. */ + /* WB13 */ + if (left_prop == RE_WBREAK_KATAKANA && right_prop == RE_WBREAK_KATAKANA) + return FALSE; + + /* Do not break from extenders. */ + /* WB13a */ + if ((IS_AHLETTER(left_prop) || left_prop == RE_WBREAK_NUMERIC || left_prop + == RE_WBREAK_KATAKANA || left_prop == RE_WBREAK_EXTENDNUMLET) && + right_prop == RE_WBREAK_EXTENDNUMLET) + return FALSE; + + /* WB13b */ + if (left_prop == RE_WBREAK_EXTENDNUMLET && (IS_AHLETTER(right_prop) || + right_prop == RE_WBREAK_NUMERIC || right_prop == RE_WBREAK_KATAKANA)) + return FALSE; + + /* Do not break within emoji flag sequences. That is, do not break between + * regional indicator (RI) symbols if there is an odd number of RI + * characters before the break point. + */ + /* WB15 and WB16 */ + pos = left_pos; + + while (pos >= state->text_start && re_get_word_break(char_at(state->text, pos)) == + RE_WBREAK_REGIONALINDICATOR) + --pos; + + if ((left_pos - pos) % 2 == 1) + return FALSE; + + /* Otherwise, break everywhere (including around ideographs). */ + /* WB999 */ + return TRUE; +} + +/* Checks whether a position is at the start/end of a word. */ +Py_LOCAL_INLINE(BOOL) unicode_at_default_word_start_or_end(RE_State* state, + Py_ssize_t text_pos, BOOL at_start) { + BOOL before; + BOOL after; + + /* Is it at a boundary? */ + if (!unicode_at_default_boundary(state, text_pos)) + return FALSE; + + /* Look at the 2 characters either side of the boundary. Are they part of a + * word? + */ + before = unicode_word_left(state, text_pos); + after = unicode_word_right(state, text_pos); + + return before != at_start && after == at_start; +} + +/* Checks whether a position is at the start of a word. */ +static BOOL unicode_at_default_word_start(RE_State* state, Py_ssize_t text_pos) + { + return unicode_at_default_word_start_or_end(state, text_pos, TRUE); +} + +/* Checks whether a position is at the end of a word. */ +static BOOL unicode_at_default_word_end(RE_State* state, Py_ssize_t text_pos) { + return unicode_at_default_word_start_or_end(state, text_pos, FALSE); +} + +/* Checks whether a position is on a grapheme boundary. + * + * The rules are defined here: + * https://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries + */ +static BOOL unicode_at_grapheme_boundary(RE_State* state, Py_ssize_t text_pos) + { + Py_UCS4 (*char_at)(void* text, Py_ssize_t pos); + Py_ssize_t left_pos; + Py_ssize_t right_pos; + Py_UCS4 left_char; + Py_UCS4 right_char; + RE_UINT32 left_prop; + RE_UINT32 right_prop; + RE_UINT32 prop; + Py_ssize_t pos; + + /* Break at the start and end of text, unless the text is empty. */ + /* GB1 and GB2 */ + if (text_pos <= state->text_start || text_pos >= state->text_end) + return state->text_end > state->text_start; + + /* In this function, left_pos is inclusive, i.e. it's the index of the + * character. + */ + char_at = state->char_at; + + left_pos = text_pos - 1; + right_pos = text_pos; + left_char = char_at(state->text, left_pos); + right_char = char_at(state->text, right_pos); + + /* Do not break between a CR and LF. Otherwise, break before and after + * controls. + */ + /* GB3 */ + left_prop = re_get_grapheme_cluster_break(left_char); + right_prop = re_get_grapheme_cluster_break(right_char); + + if (left_prop == RE_GBREAK_CR && right_prop == RE_GBREAK_LF) + return FALSE; + + /* GB4 */ + if (left_prop == RE_GBREAK_CONTROL || left_prop == RE_GBREAK_CR || + left_prop == RE_GBREAK_LF) + return TRUE; + + /* GB5 */ + if (right_prop == RE_GBREAK_CONTROL || right_prop == RE_GBREAK_CR || + right_prop == RE_GBREAK_LF) + return TRUE; + + /* Do not break Hangul syllable sequences. */ + /* GB6 */ + if (left_prop == RE_GBREAK_L && (right_prop == RE_GBREAK_L || right_prop == + RE_GBREAK_V || right_prop == RE_GBREAK_LV || right_prop == + RE_GBREAK_LVT)) + return FALSE; + + /* GB7 */ + if ((left_prop == RE_GBREAK_LV || left_prop == RE_GBREAK_V) && (right_prop + == RE_GBREAK_V || right_prop == RE_GBREAK_T)) + return FALSE; + + /* GB8 */ + if ((left_prop == RE_GBREAK_LVT || left_prop == RE_GBREAK_T) && right_prop + == RE_GBREAK_T) + return FALSE; + + /* Do not break before extending characters or ZWJ. */ + /* GB9 */ + if (right_prop == RE_GBREAK_EXTEND || right_prop == RE_GBREAK_ZWJ) + return FALSE; + + /* The GB9a and GB9b rules only apply to extended grapheme clusters: Do not + * break before SpacingMarks, or after Prepend characters. + */ + /* GB9a */ + if (right_prop == RE_GBREAK_SPACINGMARK) + return FALSE; + + /* GB9b */ + if (left_prop == RE_GBREAK_PREPEND) + return FALSE; + + /* The GB9c rule only applies to extended grapheme clusters: Do not break + * within certain combinations with Indic_Conjunct_Break (InCB)=Linker. + */ + /* GB9c */ + if (re_get_indic_conjunct_break(right_char) == RE_INCB_CONSONANT) { + BOOL has_linker; + + has_linker = FALSE; + pos = left_pos; + + do { + prop = re_get_indic_conjunct_break(char_at(state->text, pos)); + + switch (prop) { + case RE_INCB_LINKER: + has_linker = TRUE; + break; + case RE_INCB_EXTEND: + break; + case RE_INCB_CONSONANT: + if (has_linker) + return FALSE; + goto end_GB9c; + default: + goto end_GB9c; + } + + --pos; + } while (pos >= state->text_start); + } + +end_GB9c: + /* Do not break within emoji modifier sequences or emoji zwj sequences. */ + /* GB11 */ + if (left_prop == RE_GBREAK_ZWJ && re_get_extended_pictographic(right_char)) + { + pos = left_pos - 1; + + while (pos >= state->text_start && re_get_grapheme_cluster_break(char_at(state->text, + pos)) == RE_GBREAK_EXTEND) + --pos; + + if (pos >= state->text_start && re_get_extended_pictographic(char_at(state->text, + pos))) + return FALSE; + } + + /* The \p{Extended_Pictographic} values are provided as a part of the Emoji + * data in [UTS51]. Do not break within emoji flag sequences. That is, do + * not break between regional indicator (RI) symbols if there is an odd + * number of RI characters before the break point. + */ + /* GB12 and GB13 */ + if (right_prop == RE_GBREAK_REGIONALINDICATOR) { + pos = left_pos; + + while (pos >= state->text_start && re_get_grapheme_cluster_break(char_at(state->text, + pos)) == RE_GBREAK_REGIONALINDICATOR) + --pos; + + if ((left_pos - pos) % 2 == 1) + return FALSE; + } + + /* Otherwise, break everywhere. */ + /* GB999 */ + return TRUE; +} + +/* Checks whether a character is a line separator. */ +static BOOL unicode_is_line_sep(Py_UCS4 ch) { + return (0x0A <= ch && ch <= 0x0D) || ch == 0x85 || ch == 0x2028 || ch == + 0x2029; +} + +/* Checks whether a position is at the start of a line. */ +static BOOL unicode_at_line_start(RE_State* state, Py_ssize_t text_pos) { + Py_UCS4 ch; + + if (text_pos <= state->text_start) + return TRUE; + + ch = state->char_at(state->text, text_pos - 1); + + if (ch == 0x0D) { + if (text_pos >= state->text_end) + return TRUE; + + /* No line break inside CRLF. */ + return state->char_at(state->text, text_pos) != 0x0A; + } + + return (0x0A <= ch && ch <= 0x0D) || ch == 0x85 || ch == 0x2028 || ch == + 0x2029; +} + +/* Checks whether a position is at the end of a line. */ +static BOOL unicode_at_line_end(RE_State* state, Py_ssize_t text_pos) { + Py_UCS4 ch; + + if (text_pos >= state->text_end) + return TRUE; + + ch = state->char_at(state->text, text_pos); + + if (ch == 0x0A) { + if (text_pos <= state->text_start) + return TRUE; + + /* No line break inside CRLF. */ + return state->char_at(state->text, text_pos - 1) != 0x0D; + } + + return (0x0A <= ch && ch <= 0x0D) || ch == 0x85 || ch == 0x2028 || ch == + 0x2029; +} + +/* Checks whether a character could be Turkic (variants of I/i). */ +static BOOL unicode_possible_turkic(RE_LocaleInfo* locale_info, Py_UCS4 ch) { + return ch == 'I' || ch == 'i' || ch == 0x0130 || ch == 0x0131; +} + +/* Gets all the cases of a character. */ +static int unicode_all_cases(RE_LocaleInfo* locale_info, Py_UCS4 ch, Py_UCS4* + codepoints) { + return re_get_all_cases(ch, codepoints); +} + +/* Returns a character with its case folded, unless it could be Turkic + * (variants of I/i). + */ +static Py_UCS4 unicode_simple_case_fold(RE_LocaleInfo* locale_info, Py_UCS4 ch) + { + /* Is it a possible Turkic character? If so, pass it through unchanged. */ + if (ch == 'I' || ch == 'i' || ch == 0x0130 || ch == 0x0131) + return ch; + + return (Py_UCS4)re_get_simple_case_folding(ch); +} + +/* Returns a character with its case folded, unless it could be Turkic + * (variants of I/i). + */ +static int unicode_full_case_fold(RE_LocaleInfo* locale_info, Py_UCS4 ch, + Py_UCS4* folded) { + /* Is it a possible Turkic character? If so, pass it through unchanged. */ + if (ch == 'I' || ch == 'i' || ch == 0x0130 || ch == 0x0131) { + folded[0] = ch; + return 1; + } + + return re_get_full_case_folding(ch, folded); +} + +/* Gets all the case variants of Turkic 'I'. */ +static int unicode_all_turkic_i(RE_LocaleInfo* locale_info, Py_UCS4 ch, + Py_UCS4* cases) { + int count; + + count = 0; + + cases[count++] = ch; + + if (ch != 'I') + cases[count++] = 'I'; + + if (ch != 'i') + cases[count++] = 'i'; + + if (ch != 0x130) + cases[count++] = 0x130; + + if (ch != 0x131) + cases[count++] = 0x131; + + return count; + +} + +/* The handlers for Unicode characters. */ +static RE_EncodingTable unicode_encoding = { + unicode_has_property_wrapper, + unicode_at_boundary, + unicode_at_word_start, + unicode_at_word_end, + unicode_at_default_boundary, + unicode_at_default_word_start, + unicode_at_default_word_end, + unicode_at_grapheme_boundary, + unicode_is_line_sep, + unicode_at_line_start, + unicode_at_line_end, + unicode_possible_turkic, + unicode_all_cases, + unicode_simple_case_fold, + unicode_full_case_fold, + unicode_all_turkic_i, +}; + +Py_LOCAL_INLINE(PyObject*) get_object(char* module_name, char* object_name); + +/* Sets the error message. */ +Py_LOCAL_INLINE(void) set_error(int status, PyObject* object) { + TRACE(("<>\n")) + + PyErr_Clear(); + + switch (status) { + case RE_ERROR_BAD_TIMEOUT: + PyErr_SetString(PyExc_ValueError, "timeout not float or None"); + break; + case RE_ERROR_CANCELLED: + /* An exception has already been raised, so let it fly. */ + break; + case RE_ERROR_CONCURRENT: + PyErr_SetString(PyExc_ValueError, "concurrent not int or None"); + break; + case RE_ERROR_GROUP_INDEX_TYPE: + if (object) + PyErr_Format(PyExc_TypeError, + "group indices must be integers or strings, not %.200s", + object->ob_type->tp_name); + else + PyErr_Format(PyExc_TypeError, + "group indices must be integers or strings"); + break; + case RE_ERROR_ILLEGAL: + PyErr_SetString(PyExc_RuntimeError, "invalid RE code"); + break; + case RE_ERROR_INDEX: + PyErr_SetString(PyExc_TypeError, "string indices must be integers"); + break; + case RE_ERROR_INVALID_GROUP_REF: + if (!error_exception) + error_exception = get_object("regex._regex_core", "error"); + + PyErr_SetString(error_exception, "invalid group reference"); + break; + case RE_ERROR_MEMORY: + PyErr_NoMemory(); + break; + case RE_ERROR_NOT_BYTES: + PyErr_Format(PyExc_TypeError, + "expected a bytes-like object, %.200s found", + object->ob_type->tp_name); + break; + case RE_ERROR_NOT_STRING: + PyErr_Format(PyExc_TypeError, "expected string instance, %.200s found", + object->ob_type->tp_name); + break; + case RE_ERROR_NOT_UNICODE: + PyErr_Format(PyExc_TypeError, "expected str instance, %.200s found", + object->ob_type->tp_name); + break; + case RE_ERROR_NO_SUCH_GROUP: + PyErr_SetString(PyExc_IndexError, "no such group"); + break; + case RE_ERROR_REPLACEMENT: + if (!error_exception) + error_exception = get_object("regex._regex_core", "error"); + + PyErr_SetString(error_exception, "invalid replacement"); + break; + case RE_ERROR_TIMED_OUT: + PyErr_SetString(PyExc_TimeoutError, "regex timed out"); + break; + default: + /* Other error codes indicate compiler/engine bugs. */ + PyErr_SetString(PyExc_RuntimeError, + "internal error in regular expression engine"); + break; + } +} + +/* Allocates memory. + * + * Sets the Python error handler and returns NULL if the allocation fails. + */ +Py_LOCAL_INLINE(void*) re_alloc(size_t size) { + void* new_ptr; + + new_ptr = PyMem_Malloc(size); + if (!new_ptr) + set_error(RE_ERROR_MEMORY, NULL); + + return new_ptr; +} + +/* Reallocates memory. + * + * Sets the Python error handler and returns NULL if the reallocation fails. + */ +Py_LOCAL_INLINE(void*) re_realloc(void* ptr, size_t size) { + void* new_ptr; + + new_ptr = PyMem_Realloc(ptr, size); + if (!new_ptr) + set_error(RE_ERROR_MEMORY, NULL); + + return new_ptr; +} + +/* Deallocates memory. */ +Py_LOCAL_INLINE(void) re_dealloc(void* ptr) { + PyMem_Free(ptr); +} + +/* Releases the GIL if multithreading is enabled. */ +Py_LOCAL_INLINE(void) release_GIL(RE_State* state) { + if (state->is_multithreaded && !state->thread_state) + state->thread_state = PyEval_SaveThread(); +} + +/* Acquires the GIL if multithreading is enabled. */ +Py_LOCAL_INLINE(void) acquire_GIL(RE_State* state) { + if (state->is_multithreaded && state->thread_state) { + PyEval_RestoreThread(state->thread_state); + state->thread_state = NULL; + } +} + +/* Allocates memory, holding the GIL during the allocation. + * + * Sets the Python error handler and returns NULL if the allocation fails. + */ +Py_LOCAL_INLINE(void*) safe_alloc(RE_State* state, size_t size) { + void* new_ptr; + + acquire_GIL(state); + + new_ptr = re_alloc(size); + + release_GIL(state); + + return new_ptr; +} + +/* Reallocates memory, holding the GIL during the reallocation. + * + * Sets the Python error handler and returns NULL if the reallocation fails. + */ +Py_LOCAL_INLINE(void*) safe_realloc(RE_State* state, void* ptr, size_t size) { + void* new_ptr; + + acquire_GIL(state); + + new_ptr = re_realloc(ptr, size); + + release_GIL(state); + + return new_ptr; +} + +/* Deallocates memory, holding the GIL during the deallocation. */ +Py_LOCAL_INLINE(void) safe_dealloc(RE_State* state, void* ptr) { + acquire_GIL(state); + + re_dealloc(ptr); + + release_GIL(state); +} + +/* Checks whether matching has timed out. */ +Py_LOCAL_INLINE(BOOL) check_timed_out(RE_State* state) { + if (state->timeout == RE_NO_TIMEOUT) + /* No timeout. */ + return FALSE; + + if ((Py_ssize_t)(clock() - state->start_time) < state->timeout) + /* Hasn't timed out yet. */ + return FALSE; + + set_error(RE_ERROR_TIMED_OUT, NULL); + + return TRUE; +} + +/* Checks whether to cancel due to a KeyboardInterrupt or a timeout. */ +Py_LOCAL_INLINE(BOOL) safe_check_cancel(RE_State* state) { + BOOL result; + + acquire_GIL(state); + + result = (BOOL)PyErr_CheckSignals(); + + if (!result) + /* Has it timed out? */ + result = check_timed_out(state); + + release_GIL(state); + + return result; +} + +/* Initialises a stack of bytes. */ +Py_LOCAL_INLINE(BOOL) ByteStack_init(RE_State* state, ByteStack* stack) { + stack->capacity = 0; + stack->count = 0; + stack->storage = NULL; + + return TRUE; +} + +/* Finalises a stack of bytes. */ +Py_LOCAL_INLINE(void) ByteStack_fini(RE_State* state, ByteStack* stack) { + re_dealloc(stack->storage); + stack->storage = NULL; + stack->capacity = 0; + stack->count = 0; +} + +/* Resets a stack of bytes. */ +Py_LOCAL_INLINE(void) ByteStack_reset(RE_State* state, ByteStack* stack) { + stack->count = 0; +} + +/* Pushes a byte onto a stack of bytes. */ +Py_LOCAL_INLINE(BOOL) ByteStack_push(RE_State* state, ByteStack* stack, BYTE + item) { + if (stack->count >= stack->capacity) { + size_t new_capacity; + void* new_storage; + + new_capacity = stack->capacity * 2; + + if (new_capacity == 0) + new_capacity = 64; + + if (new_capacity >= RE_MEMORY_LIMIT) { + acquire_GIL(state); + set_error(RE_ERROR_MEMORY, NULL); + release_GIL(state); + return FALSE; + } + + new_storage = safe_realloc(state, stack->storage, new_capacity); + if (!new_storage) + return FALSE; + + stack->capacity = new_capacity; + stack->storage = new_storage; + } + + stack->storage[stack->count++] = item; + + return TRUE; +} + +/* Pushes a block onto a stack of bytes. */ +Py_LOCAL_INLINE(BOOL) ByteStack_push_block(RE_State* state, ByteStack* stack, + void* block, size_t count) { + size_t new_count; + + new_count = stack->count + count; + + if (new_count > stack->capacity) { + size_t new_capacity; + void* new_storage; + + new_capacity = stack->capacity; + + if (new_capacity == 0) + new_capacity = 256; + + while (new_count > new_capacity) + new_capacity *= 2; + + if (new_capacity >= RE_MEMORY_LIMIT) { + acquire_GIL(state); + set_error(RE_ERROR_MEMORY, NULL); + release_GIL(state); + return FALSE; + } + + new_storage = safe_realloc(state, stack->storage, new_capacity); + if (!new_storage) + return FALSE; + + stack->capacity = new_capacity; + stack->storage = new_storage; + } + + Py_MEMCPY(stack->storage + stack->count, block, count); + stack->count = new_count; + + return TRUE; +} + +/* Pops a byte off a stack of bytes. */ +Py_LOCAL_INLINE(BOOL) ByteStack_pop(RE_State* state, ByteStack* stack, BYTE* + item) { + if (stack->count < 1) + return FALSE; + + *item = stack->storage[--stack->count]; + + return TRUE; +} + +/* Pops a block off a stack of bytes. */ +Py_LOCAL_INLINE(BOOL) ByteStack_pop_block(RE_State* state, ByteStack* stack, + void* block, size_t count) { + if (count > stack->count) + return FALSE; + + stack->count -= count; + Py_MEMCPY(block, stack->storage + stack->count, count); + + return TRUE; +} + +/* Drops a byte off a stack of bytes. */ +Py_LOCAL_INLINE(BOOL) ByteStack_drop(RE_State* state, ByteStack* stack) { + if (stack->count < 1) + return FALSE; + + --stack->count; + + return TRUE; +} + +/* Drops a block off a stack of bytes. */ +Py_LOCAL_INLINE(BOOL) ByteStack_drop_block(RE_State* state, ByteStack* stack, + size_t count) { + if (count > stack->count) + return FALSE; + + stack->count -= count; + + return TRUE; +} + +/* Gets the top block off a stack of bytes. */ +Py_LOCAL_INLINE(BOOL) ByteStack_top_block(RE_State* state, ByteStack* stack, + void* block, size_t count) { + if (count > stack->count) + return FALSE; + + Py_MEMCPY(block, stack->storage + stack->count - count, count); + + return TRUE; +} + +/* Pushes a int8 onto a stack of bytes. */ +Py_LOCAL_INLINE(BOOL) push_int8(RE_State* state, ByteStack* stack, RE_INT8 + item) { + return ByteStack_push(state, stack, (BYTE)item); +} + +/* Pushes a uint8 onto a stack of bytes. */ +Py_LOCAL_INLINE(BOOL) push_uint8(RE_State* state, ByteStack* stack, RE_UINT8 + item) { + return ByteStack_push(state, stack, (BYTE)item); +} + +/* Pushes a bool onto a stack of bytes. */ +Py_LOCAL_INLINE(BOOL) push_bool(RE_State* state, ByteStack* stack, BOOL item) { + return ByteStack_push(state, stack, (BYTE)item); +} + +/* Pushes a Py_ssize_t onto a stack of bytes. */ +Py_LOCAL_INLINE(BOOL) push_ssize(RE_State* state, ByteStack* stack, Py_ssize_t + item) { + return ByteStack_push_block(state, stack, (void*)&item, sizeof(item)); +} + +/* Pushes a size_t onto a stack of bytes. */ +Py_LOCAL_INLINE(BOOL) push_size(RE_State* state, ByteStack* stack, size_t item) + { + return ByteStack_push_block(state, stack, (void*)&item, sizeof(item)); +} + +/* Pushes a code onto a stack of bytes. */ +Py_LOCAL_INLINE(BOOL) push_code(RE_State* state, ByteStack* stack, RE_CODE + item) { + return ByteStack_push_block(state, stack, (void*)&item, sizeof(item)); +} + +/* Pushes an int onto a stack of bytes. */ +Py_LOCAL_INLINE(BOOL) push_int(RE_State* state, ByteStack* stack, int item) { + return ByteStack_push_block(state, stack, (void*)&item, sizeof(item)); +} + +/* Pushes a pointer onto a stack of bytes. */ +Py_LOCAL_INLINE(BOOL) push_pointer(RE_State* state, ByteStack* stack, void* + item) { + return ByteStack_push_block(state, stack, (void*)&item, sizeof(item)); +} + +/* Pushes fuzzy counts onto a stack of bytes. */ +Py_LOCAL_INLINE(BOOL) push_fuzzy_counts(RE_State* state, ByteStack* stack, + size_t* fuzzy_counts) { + if (!state->is_fuzzy) + return TRUE; + + return ByteStack_push_block(state, stack, (void*)fuzzy_counts, + RE_FUZZY_COUNT * sizeof(size_t)); +} + +/* Pushes group spans onto a stack of bytes. */ +Py_LOCAL_INLINE(BOOL) push_groups(RE_State* state, ByteStack* stack) { + Py_ssize_t group_count; + Py_ssize_t g; + + group_count = (Py_ssize_t)state->pattern->true_group_count; + if (group_count == 0) + return TRUE; + + for (g = 0; g < group_count; g++) { + RE_GroupData* group; + + group = &state->groups[g]; + + if (!push_ssize(state, stack, group->current)) + return FALSE; + } + + /* stack: current#0 current#1 ... */ + + return TRUE; +} + +/* Pushes group captures and spans onto a stack of bytes. */ +Py_LOCAL_INLINE(BOOL) push_captures(RE_State* state, ByteStack* stack) { + Py_ssize_t group_count; + Py_ssize_t g; + + group_count = (Py_ssize_t)state->pattern->true_group_count; + if (group_count == 0) + return TRUE; + + for (g = 0; g < group_count; g++) { + RE_GroupData* group; + + group = &state->groups[g]; + + if (!push_size(state, stack, group->count)) + return FALSE; + if (!push_ssize(state, stack, group->current)) + return FALSE; + } + + /* stack: group[0] group[1] ... + * + * group: capture[0] capture[1] ... count current + */ + + return TRUE; +} + +/* Pushes the repeat guard data onto the stack. */ +Py_LOCAL_INLINE(BOOL) push_guard_data(RE_State* state, ByteStack* stack, + RE_GuardList* guard_list) { + if (!ByteStack_push_block(state, stack, (void*)guard_list->spans, + guard_list->count * sizeof(RE_GuardSpan))) + return FALSE; + if (!push_size(state, stack, guard_list->count)) + return FALSE; + + return TRUE; +} + +/* Pushes the repeat data onto the stack. */ +Py_LOCAL_INLINE(BOOL) push_repeat_data(RE_State* state, ByteStack* stack, + RE_RepeatData* repeat_data) { + if (!push_guard_data(state, stack, &repeat_data->body_guard_list)) + return FALSE; + if (!push_guard_data(state, stack, &repeat_data->tail_guard_list)) + return FALSE; + if (!push_size(state, stack, repeat_data->count)) + return FALSE; + if (!push_ssize(state, stack, repeat_data->start)) + return FALSE; + if (!push_size(state, stack, repeat_data->capture_change)) + return FALSE; + + return TRUE; +} + +/* Pushes the repeats onto the stack. */ +Py_LOCAL_INLINE(BOOL) push_repeats(RE_State* state, ByteStack* stack) { + PatternObject* pattern; + Py_ssize_t repeat_count; + Py_ssize_t r; + + pattern = state->pattern; + + repeat_count = (Py_ssize_t)pattern->repeat_count; + if (repeat_count == 0) + return TRUE; + + for (r = 0; r < repeat_count; r++) { + if (!push_repeat_data(state, stack, &state->repeats[r])) + return FALSE; + } + + return TRUE; +} + +/* Pushes the bstack count onto the pstack. */ +Py_LOCAL_INLINE(BOOL) push_bstack(RE_State* state) { + if (!push_size(state, &state->pstack, state->bstack.count)) + return FALSE; + + return TRUE; +} + +/* Pushes the sstack count onto the bstack. */ +Py_LOCAL_INLINE(BOOL) push_sstack(RE_State* state) { + if (!push_size(state, &state->bstack, state->sstack.count)) + return FALSE; + + return TRUE; +} + +/* Pops a int8 off a stack of bytes. */ +Py_LOCAL_INLINE(BOOL) pop_int8(RE_State* state, ByteStack* stack, RE_INT8* + item) { + return ByteStack_pop(state, stack, (BYTE*)item); +} + +/* Pops a uint8 off a stack of bytes. */ +Py_LOCAL_INLINE(BOOL) pop_uint8(RE_State* state, ByteStack* stack, RE_UINT8* + item) { + return ByteStack_pop(state, stack, (BYTE*)item); +} + +/* Pops a bool off a stack of bytes. */ +Py_LOCAL_INLINE(BOOL) pop_bool(RE_State* state, ByteStack* stack, BOOL* item) { + return ByteStack_pop(state, stack, (BYTE*)item); +} + +/* Pops a Py_ssize_t off a stack of bytes. */ +Py_LOCAL_INLINE(BOOL) pop_ssize(RE_State* state, ByteStack* stack, Py_ssize_t* + item) { + return ByteStack_pop_block(state, stack, (void*)item, sizeof(*item)); +} + +/* Pops a size_t off a stack of bytes. */ +Py_LOCAL_INLINE(BOOL) pop_size(RE_State* state, ByteStack* stack, size_t* item) + { + return ByteStack_pop_block(state, stack, (void*)item, sizeof(*item)); +} + +/* Pops a RE_CODE off a stack of bytes. */ +Py_LOCAL_INLINE(BOOL) pop_code(RE_State* state, ByteStack* stack, RE_CODE* + item) { + return ByteStack_pop_block(state, stack, (void*)item, sizeof(*item)); +} + +/* Pops an int off a stack of bytes. */ +Py_LOCAL_INLINE(BOOL) pop_int(RE_State* state, ByteStack* stack, int* item) { + return ByteStack_pop_block(state, stack, (void*)item, sizeof(*item)); +} + +/* Pops a pointer off a stack of bytes. */ +Py_LOCAL_INLINE(BOOL) pop_pointer(RE_State* state, ByteStack* stack, void** + item) { + return ByteStack_pop_block(state, stack, (void*)item, sizeof(*item)); +} + +/* Pops fuzzy counts off a stack of bytes. */ +Py_LOCAL_INLINE(BOOL) pop_fuzzy_counts(RE_State* state, ByteStack* stack, + size_t* fuzzy_counts) { + if (!state->is_fuzzy) + return TRUE; + + return ByteStack_pop_block(state, stack, (void*)fuzzy_counts, + RE_FUZZY_COUNT * sizeof(size_t)); +} + +/* Pushes group spans off a stack of bytes. */ +Py_LOCAL_INLINE(BOOL) pop_groups(RE_State* state, ByteStack* stack) { + Py_ssize_t group_count; + Py_ssize_t g; + + /* stack: current#0 current#1 ... */ + + group_count = (Py_ssize_t)state->pattern->true_group_count; + if (group_count == 0) + return TRUE; + + for (g = group_count - 1; g >= 0; g--) { + RE_GroupData* group; + + group = &state->groups[g]; + + if (!pop_ssize(state, stack, &group->current)) + return FALSE; + } + + return TRUE; +} + +/* Pops group captures and spans off a stack of bytes. */ +Py_LOCAL_INLINE(BOOL) pop_captures(RE_State* state, ByteStack* stack) { + Py_ssize_t group_count; + Py_ssize_t g; + + /* stack: group[0] group[1] ... + * + * group: capture[0] capture[1] ... count current + */ + + group_count = (Py_ssize_t)state->pattern->true_group_count; + if (group_count == 0) + return TRUE; + + for (g = group_count - 1; g >= 0; g--) { + RE_GroupData* group; + + group = &state->groups[g]; + + if (!pop_ssize(state, stack, &group->current)) + return FALSE; + if (!pop_size(state, stack, &group->count)) + return FALSE; + } + + return TRUE; +} + +/* Pops the repeat guard data off the stack. */ +Py_LOCAL_INLINE(BOOL) pop_guard_data(RE_State* state, ByteStack* stack, + RE_GuardList* guard_list) { + if (!pop_size(state, stack, &guard_list->count)) + return FALSE; + if (!ByteStack_pop_block(state, stack, (void*)guard_list->spans, + guard_list->count * sizeof(RE_GuardSpan))) + return FALSE; + + guard_list->last_text_pos = -1; + + return TRUE; +} + +/* Pops the repeat data off the stack. */ +Py_LOCAL_INLINE(BOOL) pop_repeat_data(RE_State* state, ByteStack* stack, + RE_RepeatData* repeat_data) { + if (!pop_size(state, stack, &repeat_data->capture_change)) + return FALSE; + if (!pop_ssize(state, stack, &repeat_data->start)) + return FALSE; + if (!pop_size(state, stack, &repeat_data->count)) + return FALSE; + if (!pop_guard_data(state, stack, &repeat_data->tail_guard_list)) + return FALSE; + if (!pop_guard_data(state, stack, &repeat_data->body_guard_list)) + return FALSE; + + return TRUE; +} + +/* Pops the repeats off the stack. */ +Py_LOCAL_INLINE(BOOL) pop_repeats(RE_State* state, ByteStack* stack) { + PatternObject* pattern; + Py_ssize_t repeat_count; + Py_ssize_t r; + + pattern = state->pattern; + + repeat_count = (Py_ssize_t)pattern->repeat_count; + if (repeat_count == 0) + return TRUE; + + for (r = repeat_count - 1; r >= 0; r--) { + if (!pop_repeat_data(state, stack, &state->repeats[r])) + return FALSE; + } + + return TRUE; +} + +/* Pops the bstack count off the pstack. */ +Py_LOCAL_INLINE(BOOL) pop_bstack(RE_State* state) { + if (!pop_size(state, &state->pstack, &state->bstack.count)) + return FALSE; + + return TRUE; +} + +/* Pops the sstack count off the bstack. */ +Py_LOCAL_INLINE(BOOL) pop_sstack(RE_State* state) { + if (!pop_size(state, &state->bstack, &state->sstack.count)) + return FALSE; + + return TRUE; +} + +/* Drops a uint8 off a stack of bytes. */ +Py_LOCAL_INLINE(BOOL) drop_uint8(RE_State* state, ByteStack* stack) { + return ByteStack_drop(state, stack); +} + +/* Drops a Py_ssize_t off a stack of bytes. */ +Py_LOCAL_INLINE(BOOL) drop_ssize(RE_State* state, ByteStack* stack) { + return ByteStack_drop_block(state, stack, sizeof(Py_ssize_t)); +} + +/* Drops a size_t off a stack of bytes. */ +Py_LOCAL_INLINE(BOOL) drop_size(RE_State* state, ByteStack* stack) { + return ByteStack_drop_block(state, stack, sizeof(size_t)); +} + +/* Drops a pointer off a stack of bytes. */ +Py_LOCAL_INLINE(BOOL) drop_pointer(RE_State* state, ByteStack* stack) { + return ByteStack_drop_block(state, stack, sizeof(void*)); +} + +/* Drops the bstack count off the pstack. */ +Py_LOCAL_INLINE(BOOL) drop_bstack(RE_State* state) { + return drop_size(state, &state->pstack); +} + +/* Gets the top size_t off a stack of bytes. */ +Py_LOCAL_INLINE(BOOL) top_size(RE_State* state, ByteStack* stack, size_t* item) + { + return ByteStack_top_block(state, stack, (void*)item, sizeof(*item)); +} + +/* Returns the top bstack count off the pstack. */ +Py_LOCAL_INLINE(BOOL) top_bstack(RE_State* state) { + return top_size(state, &state->pstack, &state->bstack.count); +} + +/* Checks whether a character is in a range. */ +Py_LOCAL_INLINE(BOOL) in_range(Py_UCS4 lower, Py_UCS4 upper, Py_UCS4 ch) { + return lower <= ch && ch <= upper; +} + +/* Checks whether a character is in a range, ignoring case. */ +Py_LOCAL_INLINE(BOOL) in_range_ign(RE_EncodingTable* encoding, RE_LocaleInfo* + locale_info, Py_UCS4 lower, Py_UCS4 upper, Py_UCS4 ch) { + int count; + Py_UCS4 cases[RE_MAX_CASES]; + int i; + + count = encoding->all_cases(locale_info, ch, cases); + + for (i = 0; i < count; i++) { + if (in_range(lower, upper, cases[i])) + return TRUE; + } + + return FALSE; +} + +/* Checks whether 2 characters are the same. */ +Py_LOCAL_INLINE(BOOL) same_char(Py_UCS4 ch1, Py_UCS4 ch2) { + return ch1 == ch2; +} + +/* Wrapper for calling 'same_char' via a pointer. */ +static BOOL same_char_wrapper(RE_EncodingTable* encoding, RE_LocaleInfo* + locale_info, Py_UCS4 ch1, Py_UCS4 ch2) { + return same_char(ch1, ch2); +} + +/* Checks whether 2 characters are the same, ignoring case. */ +Py_LOCAL_INLINE(BOOL) same_char_ign(RE_EncodingTable* encoding, RE_LocaleInfo* + locale_info, Py_UCS4 ch1, Py_UCS4 ch2) { + int count; + Py_UCS4 cases[RE_MAX_CASES]; + int i; + + if (ch1 == ch2) + return TRUE; + + count = encoding->all_cases(locale_info, ch1, cases); + + for (i = 1; i < count; i++) { + if (cases[i] == ch2) + return TRUE; + } + + return FALSE; +} + +/* Checks whether 2 characters are the same, ignoring case. The first character + * is already case-folded or is a possible Turkic 'I'. + */ +Py_LOCAL_INLINE(BOOL) same_char_ign_turkic(RE_EncodingTable* encoding, + RE_LocaleInfo* locale_info, Py_UCS4 ch1, Py_UCS4 ch2) { + int count; + Py_UCS4 cases[RE_MAX_CASES]; + int i; + + if (ch1 == ch2) + return TRUE; + + if (!encoding->possible_turkic(locale_info, ch1)) + return FALSE; + + count = encoding->all_turkic_i(locale_info, ch1, cases); + + for (i = 1; i < count; i++) { + if (cases[i] == ch2) + return TRUE; + } + + return FALSE; +} + +/* Wrapper for calling 'same_char' via a pointer. */ +static BOOL same_char_ign_wrapper(RE_EncodingTable* encoding, RE_LocaleInfo* + locale_info, Py_UCS4 ch1, Py_UCS4 ch2) { + return same_char_ign(encoding, locale_info, ch1, ch2); +} + +/* Checks whether a character is anything except a newline. */ +Py_LOCAL_INLINE(BOOL) matches_ANY(RE_EncodingTable* encoding, RE_Node* node, + Py_UCS4 ch) { + return ch != '\n'; +} + +/* Checks whether a character is anything except a line separator. */ +Py_LOCAL_INLINE(BOOL) matches_ANY_U(RE_EncodingTable* encoding, RE_Node* node, + Py_UCS4 ch) { + return !encoding->is_line_sep(ch); +} + +/* Checks whether 2 characters are the same. */ +Py_LOCAL_INLINE(BOOL) matches_CHARACTER(RE_EncodingTable* encoding, + RE_LocaleInfo* locale_info, RE_Node* node, Py_UCS4 ch) { + return same_char(node->values[0], ch); +} + +/* Checks whether 2 characters are the same, ignoring case. */ +Py_LOCAL_INLINE(BOOL) matches_CHARACTER_IGN(RE_EncodingTable* encoding, + RE_LocaleInfo* locale_info, RE_Node* node, Py_UCS4 ch) { + return same_char_ign(encoding, locale_info, node->values[0], ch); +} + +/* Checks whether a character has a property. */ +Py_LOCAL_INLINE(BOOL) matches_PROPERTY(RE_EncodingTable* encoding, + RE_LocaleInfo* locale_info, RE_Node* node, Py_UCS4 ch) { + return encoding->has_property(locale_info, node->values[0], ch); +} + +/* Checks whether a character has a property, ignoring case. */ +Py_LOCAL_INLINE(BOOL) matches_PROPERTY_IGN(RE_EncodingTable* encoding, + RE_LocaleInfo* locale_info, RE_Node* node, Py_UCS4 ch) { + RE_UINT32 property; + RE_UINT32 prop; + + property = node->values[0]; + prop = property >> 16; + + /* We need to do special handling of case-sensitive properties according to + * the 'encoding'. + */ + if (encoding == &unicode_encoding) { + /* We are working with Unicode. */ + if (property == RE_PROP_GC_LU || property == RE_PROP_GC_LL || property + == RE_PROP_GC_LT) { + RE_UINT32 value; + + value = re_get_general_category(ch); + + return value == RE_PROP_LU || value == RE_PROP_LL || value == + RE_PROP_LT; + } else if (prop == RE_PROP_UPPERCASE || prop == RE_PROP_LOWERCASE) + return (BOOL)re_get_cased(ch); + + /* The property is case-insensitive. */ + return unicode_has_property(property, ch); + } else if (encoding == &ascii_encoding) { + /* We are working with ASCII. */ + if (property == RE_PROP_GC_LU || property == RE_PROP_GC_LL || property + == RE_PROP_GC_LT) { + RE_UINT32 value; + + value = re_get_general_category(ch); + + return value == RE_PROP_LU || value == RE_PROP_LL || value == + RE_PROP_LT; + } else if (prop == RE_PROP_UPPERCASE || prop == RE_PROP_LOWERCASE) + return (BOOL)re_get_cased(ch); + + /* The property is case-insensitive. */ + return ascii_has_property(property, ch); + } else { + /* We are working with Locale. */ + if (property == RE_PROP_GC_LU || property == RE_PROP_GC_LL || property + == RE_PROP_GC_LT) + return locale_isupper(locale_info, ch) || + locale_islower(locale_info, ch); + else if (prop == RE_PROP_UPPERCASE || prop == RE_PROP_LOWERCASE) + return locale_isupper(locale_info, ch) || + locale_islower(locale_info, ch); + + /* The property is case-insensitive. */ + return locale_has_property(locale_info, property, ch); + } +} + +/* Checks whether a character is in a range. */ +Py_LOCAL_INLINE(BOOL) matches_RANGE(RE_EncodingTable* encoding, RE_LocaleInfo* + locale_info, RE_Node* node, Py_UCS4 ch) { + return in_range(node->values[0], node->values[1], ch); +} + +/* Checks whether a character is in a range, ignoring case. */ +Py_LOCAL_INLINE(BOOL) matches_RANGE_IGN(RE_EncodingTable* encoding, + RE_LocaleInfo* locale_info, RE_Node* node, Py_UCS4 ch) { + return in_range_ign(encoding, locale_info, node->values[0], + node->values[1], ch); +} + +Py_LOCAL_INLINE(BOOL) in_set_diff(RE_EncodingTable* encoding, RE_LocaleInfo* + locale_info, RE_Node* node, Py_UCS4 ch); +Py_LOCAL_INLINE(BOOL) in_set_inter(RE_EncodingTable* encoding, RE_LocaleInfo* + locale_info, RE_Node* node, Py_UCS4 ch); +Py_LOCAL_INLINE(BOOL) in_set_sym_diff(RE_EncodingTable* encoding, + RE_LocaleInfo* locale_info, RE_Node* node, Py_UCS4 ch); +Py_LOCAL_INLINE(BOOL) in_set_union(RE_EncodingTable* encoding, RE_LocaleInfo* + locale_info, RE_Node* node, Py_UCS4 ch); + +/* Checks whether a character matches a set member. */ +Py_LOCAL_INLINE(BOOL) matches_member(RE_EncodingTable* encoding, RE_LocaleInfo* + locale_info, RE_Node* member, Py_UCS4 ch) { + switch (member->op) { + case RE_OP_CHARACTER: + /* values are: char_code */ + TRACE(("%s %d %d\n", re_op_text[member->op], member->match, + member->values[0])) + return ch == member->values[0]; + case RE_OP_PROPERTY: + /* values are: property */ + TRACE(("%s %d %d\n", re_op_text[member->op], member->match, + member->values[0])) + return encoding->has_property(locale_info, member->values[0], ch); + case RE_OP_RANGE: + /* values are: lower, upper */ + TRACE(("%s %d %d %d\n", re_op_text[member->op], member->match, + member->values[0], member->values[1])) + return in_range(member->values[0], member->values[1], ch); + case RE_OP_SET_DIFF: + TRACE(("%s\n", re_op_text[member->op])) + return in_set_diff(encoding, locale_info, member, ch); + case RE_OP_SET_INTER: + TRACE(("%s\n", re_op_text[member->op])) + return in_set_inter(encoding, locale_info, member, ch); + case RE_OP_SET_SYM_DIFF: + TRACE(("%s\n", re_op_text[member->op])) + return in_set_sym_diff(encoding, locale_info, member, ch); + case RE_OP_SET_UNION: + TRACE(("%s\n", re_op_text[member->op])) + return in_set_union(encoding, locale_info, member, ch); + case RE_OP_STRING: + { + /* values are: char_code, char_code, ... */ + size_t i; + TRACE(("%s %d %" PY_FORMAT_SIZE_T "d\n", re_op_text[member->op], + member->match, member->value_count)) + + for (i = 0; i < member->value_count; i++) { + if (ch == member->values[i]) + return TRUE; + } + return FALSE; + } + default: + return FALSE; + } +} + +/* Checks whether a character matches a set member, ignoring case. */ +Py_LOCAL_INLINE(BOOL) matches_member_ign(RE_EncodingTable* encoding, + RE_LocaleInfo* locale_info, RE_Node* member, int case_count, Py_UCS4* cases) + { + int i; + + for (i = 0; i < case_count; i++) { + switch (member->op) { + case RE_OP_CHARACTER: + /* values are: char_code */ + TRACE(("%s %d %d\n", re_op_text[member->op], member->match, + member->values[0])) + if (cases[i] == member->values[0]) + return TRUE; + break; + case RE_OP_PROPERTY: + /* values are: property */ + TRACE(("%s %d %d\n", re_op_text[member->op], member->match, + member->values[0])) + if (encoding->has_property(locale_info, member->values[0], + cases[i])) + return TRUE; + break; + case RE_OP_RANGE: + /* values are: lower, upper */ + TRACE(("%s %d %d %d\n", re_op_text[member->op], member->match, + member->values[0], member->values[1])) + if (in_range(member->values[0], member->values[1], cases[i])) + return TRUE; + break; + case RE_OP_SET_DIFF: + TRACE(("%s\n", re_op_text[member->op])) + if (in_set_diff(encoding, locale_info, member, cases[i])) + return TRUE; + break; + case RE_OP_SET_INTER: + TRACE(("%s\n", re_op_text[member->op])) + if (in_set_inter(encoding, locale_info, member, cases[i])) + return TRUE; + break; + case RE_OP_SET_SYM_DIFF: + TRACE(("%s\n", re_op_text[member->op])) + if (in_set_sym_diff(encoding, locale_info, member, cases[i])) + return TRUE; + break; + case RE_OP_SET_UNION: + TRACE(("%s\n", re_op_text[member->op])) + if (in_set_union(encoding, locale_info, member, cases[i])) + return TRUE; + break; + case RE_OP_STRING: + { + size_t j; + TRACE(("%s %d %zd\n", re_op_text[member->op], member->match, + member->value_count)) + + for (j = 0; j < member->value_count; j++) { + if (cases[i] == member->values[j]) + return TRUE; + } + break; + } + default: + return TRUE; + } + } + + return FALSE; +} + +/* Checks whether a character is in a set difference. */ +Py_LOCAL_INLINE(BOOL) in_set_diff(RE_EncodingTable* encoding, RE_LocaleInfo* + locale_info, RE_Node* node, Py_UCS4 ch) { + RE_Node* member; + + member = node->nonstring.next_2.node; + + if (matches_member(encoding, locale_info, member, ch) != member->match) + return FALSE; + + member = member->next_1.node; + + while (member) { + if (matches_member(encoding, locale_info, member, ch) == member->match) + return FALSE; + + member = member->next_1.node; + } + + return TRUE; +} + +/* Checks whether a character is in a set difference, ignoring case. */ +Py_LOCAL_INLINE(BOOL) in_set_diff_ign(RE_EncodingTable* encoding, + RE_LocaleInfo* locale_info, RE_Node* node, int case_count, Py_UCS4* cases) { + RE_Node* member; + + member = node->nonstring.next_2.node; + + if (matches_member_ign(encoding, locale_info, member, case_count, cases) != + member->match) + return FALSE; + + member = member->next_1.node; + + while (member) { + if (matches_member_ign(encoding, locale_info, member, case_count, + cases) == member->match) + return FALSE; + + member = member->next_1.node; + } + + return TRUE; +} + +/* Checks whether a character is in a set intersection. */ +Py_LOCAL_INLINE(BOOL) in_set_inter(RE_EncodingTable* encoding, RE_LocaleInfo* + locale_info, RE_Node* node, Py_UCS4 ch) { + RE_Node* member; + + member = node->nonstring.next_2.node; + + while (member) { + if (matches_member(encoding, locale_info, member, ch) != member->match) + return FALSE; + + member = member->next_1.node; + } + + return TRUE; +} + +/* Checks whether a character is in a set intersection, ignoring case. */ +Py_LOCAL_INLINE(BOOL) in_set_inter_ign(RE_EncodingTable* encoding, + RE_LocaleInfo* locale_info, RE_Node* node, int case_count, Py_UCS4* cases) { + RE_Node* member; + + member = node->nonstring.next_2.node; + + while (member) { + if (matches_member_ign(encoding, locale_info, member, case_count, + cases) != member->match) + return FALSE; + + member = member->next_1.node; + } + + return TRUE; +} + +/* Checks whether a character is in a set symmetric difference. */ +Py_LOCAL_INLINE(BOOL) in_set_sym_diff(RE_EncodingTable* encoding, + RE_LocaleInfo* locale_info, RE_Node* node, Py_UCS4 ch) { + RE_Node* member; + BOOL result; + + member = node->nonstring.next_2.node; + + result = FALSE; + + while (member) { + if (matches_member(encoding, locale_info, member, ch) == member->match) + result = !result; + + member = member->next_1.node; + } + + return result; +} + +/* Checks whether a character is in a set symmetric difference, ignoring case. + */ +Py_LOCAL_INLINE(BOOL) in_set_sym_diff_ign(RE_EncodingTable* encoding, + RE_LocaleInfo* locale_info, RE_Node* node, int case_count, Py_UCS4* cases) { + RE_Node* member; + BOOL result; + + member = node->nonstring.next_2.node; + + result = FALSE; + + while (member) { + if (matches_member_ign(encoding, locale_info, member, case_count, + cases) == member->match) + result = !result; + + member = member->next_1.node; + } + + return result; +} + +/* Checks whether a character is in a set union. */ +Py_LOCAL_INLINE(BOOL) in_set_union(RE_EncodingTable* encoding, RE_LocaleInfo* + locale_info, RE_Node* node, Py_UCS4 ch) { + RE_Node* member; + + member = node->nonstring.next_2.node; + + while (member) { + if (matches_member(encoding, locale_info, member, ch) == member->match) + return TRUE; + + member = member->next_1.node; + } + + return FALSE; +} + +/* Checks whether a character is in a set union, ignoring case. */ +Py_LOCAL_INLINE(BOOL) in_set_union_ign(RE_EncodingTable* encoding, + RE_LocaleInfo* locale_info, RE_Node* node, int case_count, Py_UCS4* cases) { + RE_Node* member; + + member = node->nonstring.next_2.node; + + while (member) { + if (matches_member_ign(encoding, locale_info, member, case_count, + cases) == member->match) + return TRUE; + + member = member->next_1.node; + } + + return FALSE; +} + +/* Checks whether a character is in a set. */ +Py_LOCAL_INLINE(BOOL) matches_SET(RE_EncodingTable* encoding, +RE_LocaleInfo* locale_info, RE_Node* node, Py_UCS4 ch) { + switch (node->op) { + case RE_OP_SET_DIFF: + case RE_OP_SET_DIFF_REV: + return in_set_diff(encoding, locale_info, node, ch); + case RE_OP_SET_INTER: + case RE_OP_SET_INTER_REV: + return in_set_inter(encoding, locale_info, node, ch); + case RE_OP_SET_SYM_DIFF: + case RE_OP_SET_SYM_DIFF_REV: + return in_set_sym_diff(encoding, locale_info, node, ch); + case RE_OP_SET_UNION: + case RE_OP_SET_UNION_REV: + return in_set_union(encoding, locale_info, node, ch); + } + + return FALSE; +} + +/* Checks whether a character is in a set, ignoring case. */ +Py_LOCAL_INLINE(BOOL) matches_SET_IGN(RE_EncodingTable* encoding, +RE_LocaleInfo* locale_info, RE_Node* node, Py_UCS4 ch) { + Py_UCS4 cases[RE_MAX_CASES]; + int case_count; + + case_count = encoding->all_cases(locale_info, ch, cases); + + switch (node->op) { + case RE_OP_SET_DIFF_IGN: + case RE_OP_SET_DIFF_IGN_REV: + return in_set_diff_ign(encoding, locale_info, node, case_count, cases); + case RE_OP_SET_INTER_IGN: + case RE_OP_SET_INTER_IGN_REV: + return in_set_inter_ign(encoding, locale_info, node, case_count, + cases); + case RE_OP_SET_SYM_DIFF_IGN: + case RE_OP_SET_SYM_DIFF_IGN_REV: + return in_set_sym_diff_ign(encoding, locale_info, node, case_count, + cases); + case RE_OP_SET_UNION_IGN: + case RE_OP_SET_UNION_IGN_REV: + return in_set_union_ign(encoding, locale_info, node, case_count, + cases); + } + + return FALSE; +} + +/* Resets a guard list. */ +Py_LOCAL_INLINE(void) reset_guard_list(RE_GuardList* guard_list) { + guard_list->count = 0; + guard_list->last_text_pos = -1; +} + +/* Clears the groups. */ +Py_LOCAL_INLINE(void) clear_groups(RE_State* state) { + size_t i; + + for (i = 0; i < state->pattern->true_group_count; i++) { + RE_GroupData* group; + + group = &state->groups[i]; + group->count = 0; + + group->current = -1; + } +} + +/* Resets the various guards. */ +Py_LOCAL_INLINE(void) reset_guards(RE_State* state) { + size_t i; + + /* Reset the guards for the repeats. */ + for (i = 0; i < state->pattern->repeat_count; i++) { + reset_guard_list(&state->repeats[i].body_guard_list); + reset_guard_list(&state->repeats[i].tail_guard_list); + } + + /* Reset the guards for the fuzzy sections. */ + for (i = 0; i < state->pattern->fuzzy_count; i++) { + reset_guard_list(&state->fuzzy_guards[i].body_guard_list); + reset_guard_list(&state->fuzzy_guards[i].tail_guard_list); + } + + /* Reset the guards for the group calls. */ + for (i = 0; i < state->pattern->call_ref_info_count; i++) + reset_guard_list(&state->group_call_guard_list[i]); +} + +/* Initialises the state for a match. */ +Py_LOCAL_INLINE(void) init_match(RE_State* state) { + /* Reset the stacks. */ + ByteStack_reset(state, &state->sstack); + ByteStack_reset(state, &state->bstack); + ByteStack_reset(state, &state->pstack); + + state->search_anchor = state->text_pos; + state->match_pos = state->text_pos; + + /* Clear the groups. */ + clear_groups(state); + + /* Reset the guards. */ + reset_guards(state); + + /* Clear the counts and cost for matching. */ + if (state->is_fuzzy) { + memset(state->fuzzy_counts, 0, sizeof(state->fuzzy_counts)); + state->fuzzy_node = NULL; + state->fuzzy_changes.count = 0; + } + + state->total_errors = 0; + state->found_match = FALSE; + state->capture_change = 0; + state->iterations = 0; +} + +/* Checks whether a node matches only 1 character. */ +Py_LOCAL_INLINE(BOOL) node_matches_one_character(RE_Node* node) { + switch (node->op) { + case RE_OP_ANY: + case RE_OP_ANY_ALL: + case RE_OP_ANY_ALL_REV: + case RE_OP_ANY_REV: + case RE_OP_ANY_U: + case RE_OP_ANY_U_REV: + case RE_OP_CHARACTER: + case RE_OP_CHARACTER_IGN: + case RE_OP_CHARACTER_IGN_REV: + case RE_OP_CHARACTER_REV: + case RE_OP_PROPERTY: + case RE_OP_PROPERTY_IGN: + case RE_OP_PROPERTY_IGN_REV: + case RE_OP_PROPERTY_REV: + case RE_OP_RANGE: + case RE_OP_RANGE_IGN: + case RE_OP_RANGE_IGN_REV: + case RE_OP_RANGE_REV: + case RE_OP_SET_DIFF: + case RE_OP_SET_DIFF_IGN: + case RE_OP_SET_DIFF_IGN_REV: + case RE_OP_SET_DIFF_REV: + case RE_OP_SET_INTER: + case RE_OP_SET_INTER_IGN: + case RE_OP_SET_INTER_IGN_REV: + case RE_OP_SET_INTER_REV: + case RE_OP_SET_SYM_DIFF: + case RE_OP_SET_SYM_DIFF_IGN: + case RE_OP_SET_SYM_DIFF_IGN_REV: + case RE_OP_SET_SYM_DIFF_REV: + case RE_OP_SET_UNION: + case RE_OP_SET_UNION_IGN: + case RE_OP_SET_UNION_IGN_REV: + case RE_OP_SET_UNION_REV: + return TRUE; + default: + return FALSE; + } +} + +/* Locates the start node for testing ahead. */ +Py_LOCAL_INLINE(RE_Node*) locate_test_start(RE_Node* node) { + for (;;) { + switch (node->op) { + case RE_OP_BOUNDARY: + switch (node->next_1.node->op) { + case RE_OP_STRING: + case RE_OP_STRING_FLD: + case RE_OP_STRING_FLD_REV: + case RE_OP_STRING_IGN: + case RE_OP_STRING_IGN_REV: + case RE_OP_STRING_REV: + return node->next_1.node; + default: + return node; + } + case RE_OP_CALL_REF: + case RE_OP_END_GROUP: + case RE_OP_START_GROUP: + node = node->next_1.node; + break; + case RE_OP_GREEDY_REPEAT: + case RE_OP_LAZY_REPEAT: + if (node->values[1] == 0) + return node; + node = node->next_1.node; + break; + case RE_OP_GREEDY_REPEAT_ONE: + case RE_OP_LAZY_REPEAT_ONE: + if (node->values[1] == 0) + return node; + return node->nonstring.next_2.node; + case RE_OP_LOOKAROUND: + node = node->nonstring.next_2.node; + break; + default: + if (node->step == 0 && node_matches_one_character(node)) { + switch (node->next_1.node->op) { + case RE_OP_END_OF_STRING: + case RE_OP_START_OF_STRING: + return node->next_1.node; + } + } + + return node; + } + } +} + +/* Checks whether a character matches any of a set of case characters. */ +Py_LOCAL_INLINE(BOOL) any_case(Py_UCS4 ch, int case_count, Py_UCS4* cases) { + int i; + + for (i = 0; i < case_count; i++) { + if (ch == cases[i]) + return TRUE; + } + + return FALSE; +} + +/* Matches many ANYs, up to a limit. */ +Py_LOCAL_INLINE(Py_ssize_t) match_many_ANY(RE_State* state, RE_Node* node, + Py_ssize_t text_pos, Py_ssize_t limit, BOOL match) { + void* text; + + text = state->text; + + switch (state->charsize) { + case 1: + { + Py_UCS1* text_ptr; + Py_UCS1* limit_ptr; + + text_ptr = (Py_UCS1*)text + text_pos; + limit_ptr = (Py_UCS1*)text + limit; + + while (text_ptr < limit_ptr && (text_ptr[0] != '\n') == match) + ++text_ptr; + + text_pos = text_ptr - (Py_UCS1*)text; + break; + } + case 2: + { + Py_UCS2* text_ptr; + Py_UCS2* limit_ptr; + + text_ptr = (Py_UCS2*)text + text_pos; + limit_ptr = (Py_UCS2*)text + limit; + + while (text_ptr < limit_ptr && (text_ptr[0] != '\n') == match) + ++text_ptr; + + text_pos = text_ptr - (Py_UCS2*)text; + break; + } + case 4: + { + Py_UCS4* text_ptr; + Py_UCS4* limit_ptr; + + text_ptr = (Py_UCS4*)text + text_pos; + limit_ptr = (Py_UCS4*)text + limit; + + while (text_ptr < limit_ptr && (text_ptr[0] != '\n') == match) + ++text_ptr; + + text_pos = text_ptr - (Py_UCS4*)text; + break; + } + } + + return text_pos; +} + +/* Matches many ANYs, up to a limit, backwards. */ +Py_LOCAL_INLINE(Py_ssize_t) match_many_ANY_REV(RE_State* state, RE_Node* node, + Py_ssize_t text_pos, Py_ssize_t limit, BOOL match) { + void* text; + + text = state->text; + + switch (state->charsize) { + case 1: + { + Py_UCS1* text_ptr; + Py_UCS1* limit_ptr; + + text_ptr = (Py_UCS1*)text + text_pos; + limit_ptr = (Py_UCS1*)text + limit; + + while (text_ptr > limit_ptr && (text_ptr[-1] != '\n') == match) + --text_ptr; + + text_pos = text_ptr - (Py_UCS1*)text; + break; + } + case 2: + { + Py_UCS2* text_ptr; + Py_UCS2* limit_ptr; + + text_ptr = (Py_UCS2*)text + text_pos; + limit_ptr = (Py_UCS2*)text + limit; + + while (text_ptr > limit_ptr && (text_ptr[-1] != '\n') == match) + --text_ptr; + + text_pos = text_ptr - (Py_UCS2*)text; + break; + } + case 4: + { + Py_UCS4* text_ptr; + Py_UCS4* limit_ptr; + + text_ptr = (Py_UCS4*)text + text_pos; + limit_ptr = (Py_UCS4*)text + limit; + + while (text_ptr > limit_ptr && (text_ptr[-1] != '\n') == match) + --text_ptr; + + text_pos = text_ptr - (Py_UCS4*)text; + break; + } + } + + return text_pos; +} + +/* Matches many ANY_Us, up to a limit. */ +Py_LOCAL_INLINE(Py_ssize_t) match_many_ANY_U(RE_State* state, RE_Node* node, + Py_ssize_t text_pos, Py_ssize_t limit, BOOL match) { + void* text; + RE_EncodingTable* encoding; + + text = state->text; + encoding = state->encoding; + + switch (state->charsize) { + case 1: + { + Py_UCS1* text_ptr; + Py_UCS1* limit_ptr; + + text_ptr = (Py_UCS1*)text + text_pos; + limit_ptr = (Py_UCS1*)text + limit; + + if (encoding == &unicode_encoding) { + while (text_ptr < limit_ptr && unicode_is_line_sep(text_ptr[0]) != + match) + ++text_ptr; + } else { + while (text_ptr < limit_ptr && ascii_is_line_sep(text_ptr[0]) != + match) + ++text_ptr; + } + + text_pos = text_ptr - (Py_UCS1*)text; + break; + } + case 2: + { + Py_UCS2* text_ptr; + Py_UCS2* limit_ptr; + + text_ptr = (Py_UCS2*)text + text_pos; + limit_ptr = (Py_UCS2*)text + limit; + + if (encoding == &unicode_encoding) { + while (text_ptr < limit_ptr && unicode_is_line_sep(text_ptr[0]) != + match) + ++text_ptr; + } else { + while (text_ptr < limit_ptr && ascii_is_line_sep(text_ptr[0]) != + match) + ++text_ptr; + } + + text_pos = text_ptr - (Py_UCS2*)text; + break; + } + case 4: + { + Py_UCS4* text_ptr; + Py_UCS4* limit_ptr; + + text_ptr = (Py_UCS4*)text + text_pos; + limit_ptr = (Py_UCS4*)text + limit; + + if (encoding == &unicode_encoding) { + while (text_ptr < limit_ptr && unicode_is_line_sep(text_ptr[0]) != + match) + ++text_ptr; + } else { + while (text_ptr < limit_ptr && ascii_is_line_sep(text_ptr[0]) != + match) + ++text_ptr; + } + + text_pos = text_ptr - (Py_UCS4*)text; + break; + } + } + + return text_pos; +} + +/* Matches many ANY_Us, up to a limit, backwards. */ +Py_LOCAL_INLINE(Py_ssize_t) match_many_ANY_U_REV(RE_State* state, RE_Node* + node, Py_ssize_t text_pos, Py_ssize_t limit, BOOL match) { + void* text; + RE_EncodingTable* encoding; + + text = state->text; + encoding = state->encoding; + + switch (state->charsize) { + case 1: + { + Py_UCS1* text_ptr; + Py_UCS1* limit_ptr; + + text_ptr = (Py_UCS1*)text + text_pos; + limit_ptr = (Py_UCS1*)text + limit; + + if (encoding == &unicode_encoding) { + while (text_ptr > limit_ptr && unicode_is_line_sep(text_ptr[-1]) != + match) + --text_ptr; + } else { + while (text_ptr > limit_ptr && ascii_is_line_sep(text_ptr[-1]) != + match) + --text_ptr; + } + + text_pos = text_ptr - (Py_UCS1*)text; + break; + } + case 2: + { + Py_UCS2* text_ptr; + Py_UCS2* limit_ptr; + + text_ptr = (Py_UCS2*)text + text_pos; + limit_ptr = (Py_UCS2*)text + limit; + + if (encoding == &unicode_encoding) { + while (text_ptr > limit_ptr && unicode_is_line_sep(text_ptr[-1]) != + match) + --text_ptr; + } else { + while (text_ptr > limit_ptr && ascii_is_line_sep(text_ptr[-1]) != + match) + --text_ptr; + } + + text_pos = text_ptr - (Py_UCS2*)text; + break; + } + case 4: + { + Py_UCS4* text_ptr; + Py_UCS4* limit_ptr; + + text_ptr = (Py_UCS4*)text + text_pos; + limit_ptr = (Py_UCS4*)text + limit; + + if (encoding == &unicode_encoding) { + while (text_ptr > limit_ptr && unicode_is_line_sep(text_ptr[-1]) != + match) + --text_ptr; + } else { + while (text_ptr > limit_ptr && ascii_is_line_sep(text_ptr[-1]) != + match) + --text_ptr; + } + + text_pos = text_ptr - (Py_UCS4*)text; + break; + } + } + + return text_pos; +} + +/* Matches many CHARACTERs, up to a limit. */ +Py_LOCAL_INLINE(Py_ssize_t) match_many_CHARACTER(RE_State* state, RE_Node* + node, Py_ssize_t text_pos, Py_ssize_t limit, BOOL match) { + void* text; + Py_UCS4 ch; + + text = state->text; + match = node->match == match; + ch = node->values[0]; + + switch (state->charsize) { + case 1: + { + Py_UCS1* text_ptr; + Py_UCS1* limit_ptr; + + text_ptr = (Py_UCS1*)text + text_pos; + limit_ptr = (Py_UCS1*)text + limit; + + while (text_ptr < limit_ptr && (text_ptr[0] == ch) == match) + ++text_ptr; + + text_pos = text_ptr - (Py_UCS1*)text; + break; + } + case 2: + { + Py_UCS2* text_ptr; + Py_UCS2* limit_ptr; + + text_ptr = (Py_UCS2*)text + text_pos; + limit_ptr = (Py_UCS2*)text + limit; + + while (text_ptr < limit_ptr && (text_ptr[0] == ch) == match) + ++text_ptr; + + text_pos = text_ptr - (Py_UCS2*)text; + break; + } + case 4: + { + Py_UCS4* text_ptr; + Py_UCS4* limit_ptr; + + text_ptr = (Py_UCS4*)text + text_pos; + limit_ptr = (Py_UCS4*)text + limit; + + while (text_ptr < limit_ptr && (text_ptr[0] == ch) == match) + ++text_ptr; + + text_pos = text_ptr - (Py_UCS4*)text; + break; + } + } + + return text_pos; +} + +/* Matches many CHARACTERs, up to a limit, ignoring case. */ +Py_LOCAL_INLINE(Py_ssize_t) match_many_CHARACTER_IGN(RE_State* state, RE_Node* + node, Py_ssize_t text_pos, Py_ssize_t limit, BOOL match) { + void* text; + Py_UCS4 cases[RE_MAX_CASES]; + int case_count; + + text = state->text; + match = node->match == match; + case_count = state->encoding->all_cases(state->locale_info, + node->values[0], cases); + + switch (state->charsize) { + case 1: + { + Py_UCS1* text_ptr; + Py_UCS1* limit_ptr; + + text_ptr = (Py_UCS1*)text + text_pos; + limit_ptr = (Py_UCS1*)text + limit; + + while (text_ptr < limit_ptr && any_case(text_ptr[0], case_count, cases) + == match) + ++text_ptr; + + text_pos = text_ptr - (Py_UCS1*)text; + break; + } + case 2: + { + Py_UCS2* text_ptr; + Py_UCS2* limit_ptr; + + text_ptr = (Py_UCS2*)text + text_pos; + limit_ptr = (Py_UCS2*)text + limit; + + while (text_ptr < limit_ptr && any_case(text_ptr[0], case_count, cases) + == match) + ++text_ptr; + + text_pos = text_ptr - (Py_UCS2*)text; + break; + } + case 4: + { + Py_UCS4* text_ptr; + Py_UCS4* limit_ptr; + + text_ptr = (Py_UCS4*)text + text_pos; + limit_ptr = (Py_UCS4*)text + limit; + + while (text_ptr < limit_ptr && any_case(text_ptr[0], case_count, cases) + == match) + ++text_ptr; + + text_pos = text_ptr - (Py_UCS4*)text; + break; + } + } + + return text_pos; +} + +/* Matches many CHARACTERs, up to a limit, backwards, ignoring case. */ +Py_LOCAL_INLINE(Py_ssize_t) match_many_CHARACTER_IGN_REV(RE_State* state, + RE_Node* node, Py_ssize_t text_pos, Py_ssize_t limit, BOOL match) { + void* text; + Py_UCS4 cases[RE_MAX_CASES]; + int case_count; + + text = state->text; + match = node->match == match; + case_count = state->encoding->all_cases(state->locale_info, + node->values[0], cases); + + switch (state->charsize) { + case 1: + { + Py_UCS1* text_ptr; + Py_UCS1* limit_ptr; + + text_ptr = (Py_UCS1*)text + text_pos; + limit_ptr = (Py_UCS1*)text + limit; + + while (text_ptr > limit_ptr && any_case(text_ptr[-1], case_count, + cases) == match) + --text_ptr; + + text_pos = text_ptr - (Py_UCS1*)text; + break; + } + case 2: + { + Py_UCS2* text_ptr; + Py_UCS2* limit_ptr; + + text_ptr = (Py_UCS2*)text + text_pos; + limit_ptr = (Py_UCS2*)text + limit; + + while (text_ptr > limit_ptr && any_case(text_ptr[-1], case_count, + cases) == match) + --text_ptr; + + text_pos = text_ptr - (Py_UCS2*)text; + break; + } + case 4: + { + Py_UCS4* text_ptr; + Py_UCS4* limit_ptr; + + text_ptr = (Py_UCS4*)text + text_pos; + limit_ptr = (Py_UCS4*)text + limit; + + while (text_ptr > limit_ptr && any_case(text_ptr[-1], case_count, + cases) == match) + --text_ptr; + + text_pos = text_ptr - (Py_UCS4*)text; + break; + } + } + + return text_pos; +} + +/* Matches many CHARACTERs, up to a limit, backwards. */ +Py_LOCAL_INLINE(Py_ssize_t) match_many_CHARACTER_REV(RE_State* state, RE_Node* + node, Py_ssize_t text_pos, Py_ssize_t limit, BOOL match) { + void* text; + Py_UCS4 ch; + + text = state->text; + match = node->match == match; + ch = node->values[0]; + + switch (state->charsize) { + case 1: + { + Py_UCS1* text_ptr; + Py_UCS1* limit_ptr; + + text_ptr = (Py_UCS1*)text + text_pos; + limit_ptr = (Py_UCS1*)text + limit; + + while (text_ptr > limit_ptr && (text_ptr[-1] == ch) == match) + --text_ptr; + + text_pos = text_ptr - (Py_UCS1*)text; + break; + } + case 2: + { + Py_UCS2* text_ptr; + Py_UCS2* limit_ptr; + + text_ptr = (Py_UCS2*)text + text_pos; + limit_ptr = (Py_UCS2*)text + limit; + + while (text_ptr > limit_ptr && (text_ptr[-1] == ch) == match) + --text_ptr; + + text_pos = text_ptr - (Py_UCS2*)text; + break; + } + case 4: + { + Py_UCS4* text_ptr; + Py_UCS4* limit_ptr; + + text_ptr = (Py_UCS4*)text + text_pos; + limit_ptr = (Py_UCS4*)text + limit; + + while (text_ptr > limit_ptr && (text_ptr[-1] == ch) == match) + --text_ptr; + + text_pos = text_ptr - (Py_UCS4*)text; + break; + } + } + + return text_pos; +} + +/* Matches many PROPERTYs, up to a limit. */ +Py_LOCAL_INLINE(Py_ssize_t) match_many_PROPERTY(RE_State* state, RE_Node* node, + Py_ssize_t text_pos, Py_ssize_t limit, BOOL match) { + void* text; + RE_EncodingTable* encoding; + RE_LocaleInfo* locale_info; + RE_CODE property; + + text = state->text; + match = node->match == match; + encoding = state->encoding; + locale_info = state->locale_info; + property = node->values[0]; + + switch (state->charsize) { + case 1: + { + Py_UCS1* text_ptr; + Py_UCS1* limit_ptr; + + text_ptr = (Py_UCS1*)text + text_pos; + limit_ptr = (Py_UCS1*)text + limit; + + if (encoding == &unicode_encoding) { + while (text_ptr < limit_ptr && unicode_has_property(property, + text_ptr[0]) == match) + ++text_ptr; + } else if (encoding == &ascii_encoding) { + while (text_ptr < limit_ptr && ascii_has_property(property, + text_ptr[0]) == match) + ++text_ptr; + } else { + while (text_ptr < limit_ptr && locale_has_property(locale_info, + property, + text_ptr[0]) == match) + ++text_ptr; + } + + text_pos = text_ptr - (Py_UCS1*)text; + break; + } + case 2: + { + Py_UCS2* text_ptr; + Py_UCS2* limit_ptr; + + text_ptr = (Py_UCS2*)text + text_pos; + limit_ptr = (Py_UCS2*)text + limit; + + if (encoding == &unicode_encoding) { + while (text_ptr < limit_ptr && unicode_has_property(property, + text_ptr[0]) == match) + ++text_ptr; + } else if (encoding == &ascii_encoding) { + while (text_ptr < limit_ptr && ascii_has_property(property, + text_ptr[0]) == match) + ++text_ptr; + } else { + while (text_ptr < limit_ptr && locale_has_property(locale_info, + property, + text_ptr[0]) == match) + ++text_ptr; + } + + text_pos = text_ptr - (Py_UCS2*)text; + break; + } + case 4: + { + Py_UCS4* text_ptr; + Py_UCS4* limit_ptr; + + text_ptr = (Py_UCS4*)text + text_pos; + limit_ptr = (Py_UCS4*)text + limit; + + if (encoding == &unicode_encoding) { + while (text_ptr < limit_ptr && unicode_has_property(property, + text_ptr[0]) == match) + ++text_ptr; + } else if (encoding == &ascii_encoding) { + while (text_ptr < limit_ptr && ascii_has_property(property, + text_ptr[0]) == match) + ++text_ptr; + } else { + while (text_ptr < limit_ptr && locale_has_property(locale_info, + property, + text_ptr[0]) == match) + ++text_ptr; + } + + text_pos = text_ptr - (Py_UCS4*)text; + break; + } + } + + return text_pos; +} + +/* Matches many PROPERTYs, up to a limit, ignoring case. */ +Py_LOCAL_INLINE(Py_ssize_t) match_many_PROPERTY_IGN(RE_State* state, RE_Node* + node, Py_ssize_t text_pos, Py_ssize_t limit, BOOL match) { + void* text; + RE_EncodingTable* encoding; + RE_LocaleInfo* locale_info; + RE_CODE property; + + text = state->text; + match = node->match == match; + encoding = state->encoding; + locale_info = state->locale_info; + property = node->values[0]; + + switch (state->charsize) { + case 1: + { + Py_UCS1* text_ptr; + Py_UCS1* limit_ptr; + + text_ptr = (Py_UCS1*)text + text_pos; + limit_ptr = (Py_UCS1*)text + limit; + + if (encoding == &unicode_encoding) { + while (text_ptr < limit_ptr && unicode_has_property_ign(property, + text_ptr[0]) == match) + ++text_ptr; + } else if (encoding == &ascii_encoding) { + while (text_ptr < limit_ptr && ascii_has_property_ign(property, + text_ptr[0]) == match) + ++text_ptr; + } else { + while (text_ptr < limit_ptr && locale_has_property_ign(locale_info, + property, + text_ptr[0]) == match) + ++text_ptr; + } + + text_pos = text_ptr - (Py_UCS1*)text; + break; + } + case 2: + { + Py_UCS2* text_ptr; + Py_UCS2* limit_ptr; + + text_ptr = (Py_UCS2*)text + text_pos; + limit_ptr = (Py_UCS2*)text + limit; + + if (encoding == &unicode_encoding) { + while (text_ptr < limit_ptr && unicode_has_property_ign(property, + text_ptr[0]) == match) + ++text_ptr; + } else if (encoding == &ascii_encoding) { + while (text_ptr < limit_ptr && ascii_has_property_ign(property, + text_ptr[0]) == match) + ++text_ptr; + } else { + while (text_ptr < limit_ptr && locale_has_property_ign(locale_info, + property, + text_ptr[0]) == match) + ++text_ptr; + } + + text_pos = text_ptr - (Py_UCS2*)text; + break; + } + case 4: + { + Py_UCS4* text_ptr; + Py_UCS4* limit_ptr; + + text_ptr = (Py_UCS4*)text + text_pos; + limit_ptr = (Py_UCS4*)text + limit; + + if (encoding == &unicode_encoding) { + while (text_ptr < limit_ptr && unicode_has_property_ign(property, + text_ptr[0]) == match) + ++text_ptr; + } else if (encoding == &ascii_encoding) { + while (text_ptr < limit_ptr && ascii_has_property_ign(property, + text_ptr[0]) == match) + ++text_ptr; + } else { + while (text_ptr < limit_ptr && locale_has_property_ign(locale_info, + property, + text_ptr[0]) == match) + ++text_ptr; + } + + text_pos = text_ptr - (Py_UCS4*)text; + break; + } + } + + return text_pos; +} + +/* Matches many PROPERTYs, up to a limit, backwards, ignoring case. */ +Py_LOCAL_INLINE(Py_ssize_t) match_many_PROPERTY_IGN_REV(RE_State* state, + RE_Node* node, Py_ssize_t text_pos, Py_ssize_t limit, BOOL match) { + void* text; + RE_EncodingTable* encoding; + RE_LocaleInfo* locale_info; + RE_CODE property; + + text = state->text; + match = node->match == match; + encoding = state->encoding; + locale_info = state->locale_info; + property = node->values[0]; + + switch (state->charsize) { + case 1: + { + Py_UCS1* text_ptr; + Py_UCS1* limit_ptr; + + text_ptr = (Py_UCS1*)text + text_pos; + limit_ptr = (Py_UCS1*)text + limit; + + if (encoding == &unicode_encoding) { + while (text_ptr > limit_ptr && unicode_has_property_ign(property, + text_ptr[-1]) == match) + --text_ptr; + } else if (encoding == &ascii_encoding) { + while (text_ptr > limit_ptr && ascii_has_property_ign(property, + text_ptr[-1]) == match) + --text_ptr; + } else { + while (text_ptr > limit_ptr && locale_has_property_ign(locale_info, + property, + text_ptr[-1]) == match) + --text_ptr; + } + + text_pos = text_ptr - (Py_UCS1*)text; + break; + } + case 2: + { + Py_UCS2* text_ptr; + Py_UCS2* limit_ptr; + + text_ptr = (Py_UCS2*)text + text_pos; + limit_ptr = (Py_UCS2*)text + limit; + + if (encoding == &unicode_encoding) { + while (text_ptr > limit_ptr && unicode_has_property_ign(property, + text_ptr[-1]) == match) + --text_ptr; + } else if (encoding == &ascii_encoding) { + while (text_ptr > limit_ptr && ascii_has_property_ign(property, + text_ptr[-1]) == match) + --text_ptr; + } else { + while (text_ptr > limit_ptr && locale_has_property_ign(locale_info, + property, + text_ptr[-1]) == match) + --text_ptr; + } + + text_pos = text_ptr - (Py_UCS2*)text; + break; + } + case 4: + { + Py_UCS4* text_ptr; + Py_UCS4* limit_ptr; + + text_ptr = (Py_UCS4*)text + text_pos; + limit_ptr = (Py_UCS4*)text + limit; + + if (encoding == &unicode_encoding) { + while (text_ptr > limit_ptr && unicode_has_property_ign(property, + text_ptr[-1]) == match) + --text_ptr; + } else if (encoding == &ascii_encoding) { + while (text_ptr > limit_ptr && ascii_has_property_ign(property, + text_ptr[-1]) == match) + --text_ptr; + } else { + while (text_ptr > limit_ptr && locale_has_property_ign(locale_info, + property, + text_ptr[-1]) == match) + --text_ptr; + } + + text_pos = text_ptr - (Py_UCS4*)text; + break; + } + } + + return text_pos; +} + +/* Matches many PROPERTYs, up to a limit, backwards. */ +Py_LOCAL_INLINE(Py_ssize_t) match_many_PROPERTY_REV(RE_State* state, RE_Node* + node, Py_ssize_t text_pos, Py_ssize_t limit, BOOL match) { + void* text; + RE_EncodingTable* encoding; + RE_LocaleInfo* locale_info; + RE_CODE property; + + text = state->text; + match = node->match == match; + encoding = state->encoding; + locale_info = state->locale_info; + property = node->values[0]; + + switch (state->charsize) { + case 1: + { + Py_UCS1* text_ptr; + Py_UCS1* limit_ptr; + + text_ptr = (Py_UCS1*)text + text_pos; + limit_ptr = (Py_UCS1*)text + limit; + + if (encoding == &unicode_encoding) { + while (text_ptr > limit_ptr && unicode_has_property(property, + text_ptr[-1]) == match) + --text_ptr; + } else if (encoding == &ascii_encoding) { + while (text_ptr > limit_ptr && ascii_has_property(property, + text_ptr[-1]) == match) + --text_ptr; + } else { + while (text_ptr > limit_ptr && locale_has_property(locale_info, + property, + text_ptr[-1]) == match) + --text_ptr; + } + + text_pos = text_ptr - (Py_UCS1*)text; + break; + } + case 2: + { + Py_UCS2* text_ptr; + Py_UCS2* limit_ptr; + + text_ptr = (Py_UCS2*)text + text_pos; + limit_ptr = (Py_UCS2*)text + limit; + + if (encoding == &unicode_encoding) { + while (text_ptr > limit_ptr && unicode_has_property(property, + text_ptr[-1]) == match) + --text_ptr; + } else if (encoding == &ascii_encoding) { + while (text_ptr > limit_ptr && ascii_has_property(property, + text_ptr[-1]) == match) + --text_ptr; + } else { + while (text_ptr > limit_ptr && locale_has_property(locale_info, + property, + text_ptr[-1]) == match) + --text_ptr; + } + + text_pos = text_ptr - (Py_UCS2*)text; + break; + } + case 4: + { + Py_UCS4* text_ptr; + Py_UCS4* limit_ptr; + + text_ptr = (Py_UCS4*)text + text_pos; + limit_ptr = (Py_UCS4*)text + limit; + + if (encoding == &unicode_encoding) { + while (text_ptr > limit_ptr && unicode_has_property(property, + text_ptr[-1]) == match) + --text_ptr; + } else if (encoding == &ascii_encoding) { + while (text_ptr > limit_ptr && ascii_has_property(property, + text_ptr[-1]) == match) + --text_ptr; + } else { + while (text_ptr > limit_ptr && locale_has_property(locale_info, + property, + text_ptr[-1]) == match) + --text_ptr; + } + + text_pos = text_ptr - (Py_UCS4*)text; + break; + } + } + + return text_pos; +} + +/* Matches many RANGEs, up to a limit. */ +Py_LOCAL_INLINE(Py_ssize_t) match_many_RANGE(RE_State* state, RE_Node* node, + Py_ssize_t text_pos, Py_ssize_t limit, BOOL match) { + void* text; + RE_EncodingTable* encoding; + RE_LocaleInfo* locale_info; + + text = state->text; + match = node->match == match; + encoding = state->encoding; + locale_info = state->locale_info; + + switch (state->charsize) { + case 1: + { + Py_UCS1* text_ptr; + Py_UCS1* limit_ptr; + + text_ptr = (Py_UCS1*)text + text_pos; + limit_ptr = (Py_UCS1*)text + limit; + + while (text_ptr < limit_ptr && matches_RANGE(encoding, locale_info, + node, text_ptr[0]) == match) + ++text_ptr; + + text_pos = text_ptr - (Py_UCS1*)text; + break; + } + case 2: + { + Py_UCS2* text_ptr; + Py_UCS2* limit_ptr; + + text_ptr = (Py_UCS2*)text + text_pos; + limit_ptr = (Py_UCS2*)text + limit; + + while (text_ptr < limit_ptr && matches_RANGE(encoding, locale_info, + node, text_ptr[0]) == match) + ++text_ptr; + + text_pos = text_ptr - (Py_UCS2*)text; + break; + } + case 4: + { + Py_UCS4* text_ptr; + Py_UCS4* limit_ptr; + + text_ptr = (Py_UCS4*)text + text_pos; + limit_ptr = (Py_UCS4*)text + limit; + + while (text_ptr < limit_ptr && matches_RANGE(encoding, locale_info, + node, text_ptr[0]) == match) + ++text_ptr; + + text_pos = text_ptr - (Py_UCS4*)text; + break; + } + } + + return text_pos; +} + +/* Matches many RANGEs, up to a limit, ignoring case. */ +Py_LOCAL_INLINE(Py_ssize_t) match_many_RANGE_IGN(RE_State* state, RE_Node* + node, Py_ssize_t text_pos, Py_ssize_t limit, BOOL match) { + void* text; + RE_EncodingTable* encoding; + RE_LocaleInfo* locale_info; + + text = state->text; + match = node->match == match; + encoding = state->encoding; + locale_info = state->locale_info; + + switch (state->charsize) { + case 1: + { + Py_UCS1* text_ptr; + Py_UCS1* limit_ptr; + + text_ptr = (Py_UCS1*)text + text_pos; + limit_ptr = (Py_UCS1*)text + limit; + + while (text_ptr < limit_ptr && matches_RANGE_IGN(encoding, locale_info, + node, text_ptr[0]) == match) + ++text_ptr; + + text_pos = text_ptr - (Py_UCS1*)text; + break; + } + case 2: + { + Py_UCS2* text_ptr; + Py_UCS2* limit_ptr; + + text_ptr = (Py_UCS2*)text + text_pos; + limit_ptr = (Py_UCS2*)text + limit; + + while (text_ptr < limit_ptr && matches_RANGE_IGN(encoding, locale_info, + node, text_ptr[0]) == match) + ++text_ptr; + + text_pos = text_ptr - (Py_UCS2*)text; + break; + } + case 4: + { + Py_UCS4* text_ptr; + Py_UCS4* limit_ptr; + + text_ptr = (Py_UCS4*)text + text_pos; + limit_ptr = (Py_UCS4*)text + limit; + + while (text_ptr < limit_ptr && matches_RANGE_IGN(encoding, locale_info, + node, text_ptr[0]) == match) + ++text_ptr; + + text_pos = text_ptr - (Py_UCS4*)text; + break; + } + } + + return text_pos; +} + +/* Matches many RANGEs, up to a limit, backwards, ignoring case. */ +Py_LOCAL_INLINE(Py_ssize_t) match_many_RANGE_IGN_REV(RE_State* state, RE_Node* + node, Py_ssize_t text_pos, Py_ssize_t limit, BOOL match) { + void* text; + RE_EncodingTable* encoding; + RE_LocaleInfo* locale_info; + + text = state->text; + match = node->match == match; + encoding = state->encoding; + locale_info = state->locale_info; + + switch (state->charsize) { + case 1: + { + Py_UCS1* text_ptr; + Py_UCS1* limit_ptr; + + text_ptr = (Py_UCS1*)text + text_pos; + limit_ptr = (Py_UCS1*)text + limit; + + while (text_ptr > limit_ptr && matches_RANGE_IGN(encoding, locale_info, + node, text_ptr[-1]) == match) + --text_ptr; + + text_pos = text_ptr - (Py_UCS1*)text; + break; + } + case 2: + { + Py_UCS2* text_ptr; + Py_UCS2* limit_ptr; + + text_ptr = (Py_UCS2*)text + text_pos; + limit_ptr = (Py_UCS2*)text + limit; + + while (text_ptr > limit_ptr && matches_RANGE_IGN(encoding, locale_info, + node, text_ptr[-1]) == match) + --text_ptr; + + text_pos = text_ptr - (Py_UCS2*)text; + break; + } + case 4: + { + Py_UCS4* text_ptr; + Py_UCS4* limit_ptr; + + text_ptr = (Py_UCS4*)text + text_pos; + limit_ptr = (Py_UCS4*)text + limit; + + while (text_ptr > limit_ptr && matches_RANGE_IGN(encoding, locale_info, + node, text_ptr[-1]) == match) + --text_ptr; + + text_pos = text_ptr - (Py_UCS4*)text; + break; + } + } + + return text_pos; +} + +/* Matches many RANGEs, up to a limit, backwards. */ +Py_LOCAL_INLINE(Py_ssize_t) match_many_RANGE_REV(RE_State* state, RE_Node* + node, Py_ssize_t text_pos, Py_ssize_t limit, BOOL match) { + void* text; + RE_EncodingTable* encoding; + RE_LocaleInfo* locale_info; + + text = state->text; + match = node->match == match; + encoding = state->encoding; + locale_info = state->locale_info; + + switch (state->charsize) { + case 1: + { + Py_UCS1* text_ptr; + Py_UCS1* limit_ptr; + + text_ptr = (Py_UCS1*)text + text_pos; + limit_ptr = (Py_UCS1*)text + limit; + + while (text_ptr > limit_ptr && matches_RANGE(encoding, locale_info, + node, text_ptr[-1]) == match) + --text_ptr; + + text_pos = text_ptr - (Py_UCS1*)text; + break; + } + case 2: + { + Py_UCS2* text_ptr; + Py_UCS2* limit_ptr; + + text_ptr = (Py_UCS2*)text + text_pos; + limit_ptr = (Py_UCS2*)text + limit; + + while (text_ptr > limit_ptr && matches_RANGE(encoding, locale_info, + node, text_ptr[-1]) == match) + --text_ptr; + + text_pos = text_ptr - (Py_UCS2*)text; + break; + } + case 4: + { + Py_UCS4* text_ptr; + Py_UCS4* limit_ptr; + + text_ptr = (Py_UCS4*)text + text_pos; + limit_ptr = (Py_UCS4*)text + limit; + + while (text_ptr > limit_ptr && matches_RANGE(encoding, locale_info, + node, text_ptr[-1]) == match) + --text_ptr; + + text_pos = text_ptr - (Py_UCS4*)text; + break; + } + } + + return text_pos; +} + +/* Matches many SETs, up to a limit. */ +Py_LOCAL_INLINE(Py_ssize_t) match_many_SET(RE_State* state, RE_Node* node, + Py_ssize_t text_pos, Py_ssize_t limit, BOOL match) { + void* text; + RE_EncodingTable* encoding; + RE_LocaleInfo* locale_info; + + text = state->text; + match = node->match == match; + encoding = state->encoding; + locale_info = state->locale_info; + + switch (state->charsize) { + case 1: + { + Py_UCS1* text_ptr; + Py_UCS1* limit_ptr; + + text_ptr = (Py_UCS1*)text + text_pos; + limit_ptr = (Py_UCS1*)text + limit; + + while (text_ptr < limit_ptr && matches_SET(encoding, locale_info, node, + text_ptr[0]) == match) + ++text_ptr; + + text_pos = text_ptr - (Py_UCS1*)text; + break; + } + case 2: + { + Py_UCS2* text_ptr; + Py_UCS2* limit_ptr; + + text_ptr = (Py_UCS2*)text + text_pos; + limit_ptr = (Py_UCS2*)text + limit; + + while (text_ptr < limit_ptr && matches_SET(encoding, locale_info, node, + text_ptr[0]) == match) + ++text_ptr; + + text_pos = text_ptr - (Py_UCS2*)text; + break; + } + case 4: + { + Py_UCS4* text_ptr; + Py_UCS4* limit_ptr; + + text_ptr = (Py_UCS4*)text + text_pos; + limit_ptr = (Py_UCS4*)text + limit; + + while (text_ptr < limit_ptr && matches_SET(encoding, locale_info, node, + text_ptr[0]) == match) + ++text_ptr; + + text_pos = text_ptr - (Py_UCS4*)text; + break; + } + } + + return text_pos; +} + +/* Matches many SETs, up to a limit, ignoring case. */ +Py_LOCAL_INLINE(Py_ssize_t) match_many_SET_IGN(RE_State* state, RE_Node* node, + Py_ssize_t text_pos, Py_ssize_t limit, BOOL match) { + void* text; + RE_EncodingTable* encoding; + RE_LocaleInfo* locale_info; + + text = state->text; + match = node->match == match; + encoding = state->encoding; + locale_info = state->locale_info; + + switch (state->charsize) { + case 1: + { + Py_UCS1* text_ptr; + Py_UCS1* limit_ptr; + + text_ptr = (Py_UCS1*)text + text_pos; + limit_ptr = (Py_UCS1*)text + limit; + + while (text_ptr < limit_ptr && matches_SET_IGN(encoding, locale_info, + node, text_ptr[0]) == match) + ++text_ptr; + + text_pos = text_ptr - (Py_UCS1*)text; + break; + } + case 2: + { + Py_UCS2* text_ptr; + Py_UCS2* limit_ptr; + + text_ptr = (Py_UCS2*)text + text_pos; + limit_ptr = (Py_UCS2*)text + limit; + + while (text_ptr < limit_ptr && matches_SET_IGN(encoding, locale_info, + node, text_ptr[0]) == match) + ++text_ptr; + + text_pos = text_ptr - (Py_UCS2*)text; + break; + } + case 4: + { + Py_UCS4* text_ptr; + Py_UCS4* limit_ptr; + + text_ptr = (Py_UCS4*)text + text_pos; + limit_ptr = (Py_UCS4*)text + limit; + + while (text_ptr < limit_ptr && matches_SET_IGN(encoding, locale_info, + node, text_ptr[0]) == match) + ++text_ptr; + + text_pos = text_ptr - (Py_UCS4*)text; + break; + } + } + + return text_pos; +} + +/* Matches many SETs, up to a limit, backwards, ignoring case. */ +Py_LOCAL_INLINE(Py_ssize_t) match_many_SET_IGN_REV(RE_State* state, RE_Node* + node, Py_ssize_t text_pos, Py_ssize_t limit, BOOL match) { + void* text; + RE_EncodingTable* encoding; + RE_LocaleInfo* locale_info; + + text = state->text; + match = node->match == match; + encoding = state->encoding; + locale_info = state->locale_info; + + switch (state->charsize) { + case 1: + { + Py_UCS1* text_ptr; + Py_UCS1* limit_ptr; + + text_ptr = (Py_UCS1*)text + text_pos; + limit_ptr = (Py_UCS1*)text + limit; + + while (text_ptr > limit_ptr && matches_SET_IGN(encoding, locale_info, + node, text_ptr[-1]) == match) + --text_ptr; + + text_pos = text_ptr - (Py_UCS1*)text; + break; + } + case 2: + { + Py_UCS2* text_ptr; + Py_UCS2* limit_ptr; + + text_ptr = (Py_UCS2*)text + text_pos; + limit_ptr = (Py_UCS2*)text + limit; + + while (text_ptr > limit_ptr && matches_SET_IGN(encoding, locale_info, + node, text_ptr[-1]) == match) + --text_ptr; + + text_pos = text_ptr - (Py_UCS2*)text; + break; + } + case 4: + { + Py_UCS4* text_ptr; + Py_UCS4* limit_ptr; + + text_ptr = (Py_UCS4*)text + text_pos; + limit_ptr = (Py_UCS4*)text + limit; + + while (text_ptr > limit_ptr && matches_SET_IGN(encoding, locale_info, + node, text_ptr[-1]) == match) + --text_ptr; + + text_pos = text_ptr - (Py_UCS4*)text; + break; + } + } + + return text_pos; +} + +/* Matches many SETs, up to a limit, backwards. */ +Py_LOCAL_INLINE(Py_ssize_t) match_many_SET_REV(RE_State* state, RE_Node* node, + Py_ssize_t text_pos, Py_ssize_t limit, BOOL match) { + void* text; + RE_EncodingTable* encoding; + RE_LocaleInfo* locale_info; + + text = state->text; + match = node->match == match; + encoding = state->encoding; + locale_info = state->locale_info; + + switch (state->charsize) { + case 1: + { + Py_UCS1* text_ptr; + Py_UCS1* limit_ptr; + + text_ptr = (Py_UCS1*)text + text_pos; + limit_ptr = (Py_UCS1*)text + limit; + + while (text_ptr > limit_ptr && matches_SET(encoding, locale_info, node, + text_ptr[-1]) == match) + --text_ptr; + + text_pos = text_ptr - (Py_UCS1*)text; + break; + } + case 2: + { + Py_UCS2* text_ptr; + Py_UCS2* limit_ptr; + + text_ptr = (Py_UCS2*)text + text_pos; + limit_ptr = (Py_UCS2*)text + limit; + + while (text_ptr > limit_ptr && matches_SET(encoding, locale_info, node, + text_ptr[-1]) == match) + --text_ptr; + + text_pos = text_ptr - (Py_UCS2*)text; + break; + } + case 4: + { + Py_UCS4* text_ptr; + Py_UCS4* limit_ptr; + + text_ptr = (Py_UCS4*)text + text_pos; + limit_ptr = (Py_UCS4*)text + limit; + + while (text_ptr > limit_ptr && matches_SET(encoding, locale_info, node, + text_ptr[-1]) == match) + --text_ptr; + + text_pos = text_ptr - (Py_UCS4*)text; + break; + } + } + + return text_pos; +} + +/* Counts a repeated character pattern. */ +Py_LOCAL_INLINE(size_t) count_one(RE_State* state, RE_Node* node, Py_ssize_t + text_pos, size_t max_count, BOOL* is_partial) { + size_t count; + + *is_partial = FALSE; + + if (max_count < 1) + return 0; + + switch (node->op) { + case RE_OP_ANY: + count = min_size_t((size_t)(state->slice_end - text_pos), max_count); + + count = (size_t)(match_many_ANY(state, node, text_pos, text_pos + + (Py_ssize_t)count, TRUE) - text_pos); + + *is_partial = count == (size_t)(state->text_end - text_pos) && count + < max_count && state->partial_side == RE_PARTIAL_RIGHT; + + return count; + case RE_OP_ANY_ALL: + count = min_size_t((size_t)(state->slice_end - text_pos), max_count); + + *is_partial = count == (size_t)(state->text_end - text_pos) && count + < max_count && state->partial_side == RE_PARTIAL_RIGHT; + + return count; + case RE_OP_ANY_ALL_REV: + count = min_size_t((size_t)(text_pos - state->slice_start), max_count); + + *is_partial = count == (size_t)(text_pos) && count < max_count && + state->partial_side == RE_PARTIAL_LEFT; + + return count; + case RE_OP_ANY_REV: + count = min_size_t((size_t)(text_pos - state->slice_start), max_count); + + count = (size_t)(text_pos - match_many_ANY_REV(state, node, text_pos, + text_pos - (Py_ssize_t)count, TRUE)); + + *is_partial = count == (size_t)(text_pos) && count < max_count && + state->partial_side == RE_PARTIAL_LEFT; + + return count; + case RE_OP_ANY_U: + count = min_size_t((size_t)(state->slice_end - text_pos), max_count); + + count = (size_t)(match_many_ANY_U(state, node, text_pos, text_pos + + (Py_ssize_t)count, TRUE) - text_pos); + + *is_partial = count == (size_t)(state->text_end - text_pos) && count + < max_count && state->partial_side == RE_PARTIAL_RIGHT; + + return count; + case RE_OP_ANY_U_REV: + count = min_size_t((size_t)(text_pos - state->slice_start), max_count); + + count = (size_t)(text_pos - match_many_ANY_U_REV(state, node, text_pos, + text_pos - (Py_ssize_t)count, TRUE)); + + *is_partial = count == (size_t)(text_pos) && count < max_count && + state->partial_side == RE_PARTIAL_LEFT; + + return count; + case RE_OP_CHARACTER: + count = min_size_t((size_t)(state->slice_end - text_pos), max_count); + + count = (size_t)(match_many_CHARACTER(state, node, text_pos, text_pos + + (Py_ssize_t)count, TRUE) - text_pos); + + *is_partial = count == (size_t)(state->text_end - text_pos) && count + < max_count && state->partial_side == RE_PARTIAL_RIGHT; + + return count; + case RE_OP_CHARACTER_IGN: + count = min_size_t((size_t)(state->slice_end - text_pos), max_count); + + count = (size_t)(match_many_CHARACTER_IGN(state, node, text_pos, + text_pos + (Py_ssize_t)count, TRUE) - text_pos); + + *is_partial = count == (size_t)(state->text_end - text_pos) && count + < max_count && state->partial_side == RE_PARTIAL_RIGHT; + + return count; + case RE_OP_CHARACTER_IGN_REV: + count = min_size_t((size_t)(text_pos - state->slice_start), max_count); + + count = (size_t)(text_pos - match_many_CHARACTER_IGN_REV(state, node, + text_pos, text_pos - (Py_ssize_t)count, TRUE)); + + *is_partial = count == (size_t)(text_pos) && count < max_count && + state->partial_side == RE_PARTIAL_LEFT; + + return count; + case RE_OP_CHARACTER_REV: + count = min_size_t((size_t)(text_pos - state->slice_start), max_count); + + count = (size_t)(text_pos - match_many_CHARACTER_REV(state, node, + text_pos, text_pos - (Py_ssize_t)count, TRUE)); + + *is_partial = count == (size_t)(text_pos) && count < max_count && + state->partial_side == RE_PARTIAL_LEFT; + + return count; + case RE_OP_PROPERTY: + count = min_size_t((size_t)(state->slice_end - text_pos), max_count); + + count = (size_t)(match_many_PROPERTY(state, node, text_pos, text_pos + + (Py_ssize_t)count, TRUE) - text_pos); + + *is_partial = count == (size_t)(state->text_end - text_pos) && count + < max_count && state->partial_side == RE_PARTIAL_RIGHT; + + return count; + case RE_OP_PROPERTY_IGN: + count = min_size_t((size_t)(state->slice_end - text_pos), max_count); + + count = (size_t)(match_many_PROPERTY_IGN(state, node, text_pos, + text_pos + (Py_ssize_t)count, TRUE) - text_pos); + + *is_partial = count == (size_t)(state->text_end - text_pos) && count + < max_count && state->partial_side == RE_PARTIAL_RIGHT; + + return count; + case RE_OP_PROPERTY_IGN_REV: + count = min_size_t((size_t)(text_pos - state->slice_start), max_count); + + count = (size_t)(text_pos - match_many_PROPERTY_IGN_REV(state, node, + text_pos, text_pos - (Py_ssize_t)count, TRUE)); + + *is_partial = count == (size_t)(text_pos) && count < max_count && + state->partial_side == RE_PARTIAL_LEFT; + + return count; + case RE_OP_PROPERTY_REV: + count = min_size_t((size_t)(text_pos - state->slice_start), max_count); + + count = (size_t)(text_pos - match_many_PROPERTY_REV(state, node, + text_pos, text_pos - (Py_ssize_t)count, TRUE)); + + *is_partial = count == (size_t)(text_pos) && count < max_count && + state->partial_side == RE_PARTIAL_LEFT; + + return count; + case RE_OP_RANGE: + count = min_size_t((size_t)(state->slice_end - text_pos), max_count); + + count = (size_t)(match_many_RANGE(state, node, text_pos, text_pos + + (Py_ssize_t)count, TRUE) - text_pos); + + *is_partial = count == (size_t)(state->text_end - text_pos) && count + < max_count && state->partial_side == RE_PARTIAL_RIGHT; + + return count; + case RE_OP_RANGE_IGN: + count = min_size_t((size_t)(state->slice_end - text_pos), max_count); + + count = (size_t)(match_many_RANGE_IGN(state, node, text_pos, text_pos + + (Py_ssize_t)count, TRUE) - text_pos); + + *is_partial = count == (size_t)(state->text_end - text_pos) && count + < max_count && state->partial_side == RE_PARTIAL_RIGHT; + + return count; + case RE_OP_RANGE_IGN_REV: + count = min_size_t((size_t)(text_pos - state->slice_start), max_count); + + count = (size_t)(text_pos - match_many_RANGE_IGN_REV(state, node, + text_pos, text_pos - (Py_ssize_t)count, TRUE)); + + *is_partial = count == (size_t)(text_pos) && count < max_count && + state->partial_side == RE_PARTIAL_LEFT; + + return count; + case RE_OP_RANGE_REV: + count = min_size_t((size_t)(text_pos - state->slice_start), max_count); + + count = (size_t)(text_pos - match_many_RANGE_REV(state, node, text_pos, + text_pos - (Py_ssize_t)count, TRUE)); + + *is_partial = count == (size_t)(text_pos) && count < max_count && + state->partial_side == RE_PARTIAL_LEFT; + + return count; + case RE_OP_SET_DIFF: + case RE_OP_SET_INTER: + case RE_OP_SET_SYM_DIFF: + case RE_OP_SET_UNION: + count = min_size_t((size_t)(state->slice_end - text_pos), max_count); + + count = (size_t)(match_many_SET(state, node, text_pos, text_pos + + (Py_ssize_t)count, TRUE) - text_pos); + + *is_partial = count == (size_t)(state->text_end - text_pos) && count + < max_count && state->partial_side == RE_PARTIAL_RIGHT; + + return count; + case RE_OP_SET_DIFF_IGN: + case RE_OP_SET_INTER_IGN: + case RE_OP_SET_SYM_DIFF_IGN: + case RE_OP_SET_UNION_IGN: + count = min_size_t((size_t)(state->slice_end - text_pos), max_count); + + count = (size_t)(match_many_SET_IGN(state, node, text_pos, text_pos + + (Py_ssize_t)count, TRUE) - text_pos); + + *is_partial = count == (size_t)(state->text_end - text_pos) && count + < max_count && state->partial_side == RE_PARTIAL_RIGHT; + + return count; + case RE_OP_SET_DIFF_IGN_REV: + case RE_OP_SET_INTER_IGN_REV: + case RE_OP_SET_SYM_DIFF_IGN_REV: + case RE_OP_SET_UNION_IGN_REV: + count = min_size_t((size_t)(text_pos - state->slice_start), max_count); + + count = (size_t)(text_pos - match_many_SET_IGN_REV(state, node, + text_pos, text_pos - (Py_ssize_t)count, TRUE)); + + *is_partial = count == (size_t)(text_pos) && count < max_count && + state->partial_side == RE_PARTIAL_LEFT; + + return count; + case RE_OP_SET_DIFF_REV: + case RE_OP_SET_INTER_REV: + case RE_OP_SET_SYM_DIFF_REV: + case RE_OP_SET_UNION_REV: + count = min_size_t((size_t)(text_pos - state->slice_start), max_count); + + count = (size_t)(text_pos - match_many_SET_REV(state, node, text_pos, + text_pos - (Py_ssize_t)count, TRUE)); + + *is_partial = count == (size_t)(text_pos) && count < max_count && + state->partial_side == RE_PARTIAL_LEFT; + + return count; + } + + return 0; +} + +/* Performs a simple string search. */ +Py_LOCAL_INLINE(Py_ssize_t) simple_string_search(RE_State* state, RE_Node* + node, Py_ssize_t text_pos, Py_ssize_t limit, BOOL* is_partial) { + Py_ssize_t length; + RE_CODE* values; + Py_UCS4 check_char; + + length = (Py_ssize_t)node->value_count; + values = node->values; + check_char = values[0]; + + *is_partial = FALSE; + + switch (state->charsize) { + case 1: + { + Py_UCS1* text = (Py_UCS1*)state->text; + Py_UCS1* text_ptr = text + text_pos; + Py_UCS1* limit_ptr = text + limit; + + while (text_ptr < limit_ptr) { + if (text_ptr[0] == check_char) { + Py_ssize_t s_pos; + + s_pos = 1; + + for (;;) { + if (s_pos >= length) + /* End of search string. */ + return text_ptr - text; + + if (text_ptr + s_pos >= limit_ptr) { + /* Off the end of the text. */ + if (state->partial_side == RE_PARTIAL_RIGHT) { + /* Partial match. */ + *is_partial = TRUE; + return text_ptr - text; + } + + return -1; + + } + + if (!same_char(text_ptr[s_pos], values[s_pos])) + break; + + ++s_pos; + } + } + + ++text_ptr; + } + text_pos = text_ptr - text; + break; + } + case 2: + { + Py_UCS2* text = (Py_UCS2*)state->text; + Py_UCS2* text_ptr = text + text_pos; + Py_UCS2* limit_ptr = text + limit; + + while (text_ptr < limit_ptr) { + if (text_ptr[0] == check_char) { + Py_ssize_t s_pos; + + s_pos = 1; + + for (;;) { + if (s_pos >= length) + /* End of search string. */ + return text_ptr - text; + + if (text_ptr + s_pos >= limit_ptr) { + /* Off the end of the text. */ + if (state->partial_side == RE_PARTIAL_RIGHT) { + /* Partial match. */ + *is_partial = TRUE; + return text_ptr - text; + } + + return -1; + + } + + if (!same_char(text_ptr[s_pos], values[s_pos])) + break; + + ++s_pos; + } + } + + ++text_ptr; + } + text_pos = text_ptr - text; + break; + } + case 4: + { + Py_UCS4* text = (Py_UCS4*)state->text; + Py_UCS4* text_ptr = text + text_pos; + Py_UCS4* limit_ptr = text + limit; + + while (text_ptr < limit_ptr) { + if (text_ptr[0] == check_char) { + Py_ssize_t s_pos; + + s_pos = 1; + + for (;;) { + if (s_pos >= length) + /* End of search string. */ + return text_ptr - text; + + if (text_ptr + s_pos >= limit_ptr) { + /* Off the end of the text. */ + if (state->partial_side == RE_PARTIAL_RIGHT) { + /* Partial match. */ + *is_partial = TRUE; + return text_ptr - text; + } + + return -1; + + } + + if (!same_char(text_ptr[s_pos], values[s_pos])) + break; + + ++s_pos; + } + } + + ++text_ptr; + } + text_pos = text_ptr - text; + break; + } + } + + /* Off the end of the text. */ + if (state->partial_side == RE_PARTIAL_RIGHT) { + /* Partial match. */ + *is_partial = TRUE; + return text_pos; + } + + return -1; +} + +/* Performs a simple string search, ignoring case. */ +Py_LOCAL_INLINE(Py_ssize_t) simple_string_search_ign(RE_State* state, RE_Node* + node, Py_ssize_t text_pos, Py_ssize_t limit, BOOL* is_partial) { + Py_ssize_t length; + RE_CODE* values; + RE_EncodingTable* encoding; + RE_LocaleInfo* locale_info; + Py_UCS4 cases[RE_MAX_CASES]; + int case_count; + + length = (Py_ssize_t)node->value_count; + values = node->values; + encoding = state->encoding; + locale_info = state->locale_info; + case_count = encoding->all_cases(locale_info, values[0], cases); + + *is_partial = FALSE; + + switch (state->charsize) { + case 1: + { + Py_UCS1* text = (Py_UCS1*)state->text; + Py_UCS1* text_ptr = text + text_pos; + Py_UCS1* limit_ptr = text + limit; + + while (text_ptr < limit_ptr) { + if (any_case(text_ptr[0], case_count, cases)) { + Py_ssize_t s_pos; + + s_pos = 1; + + for (;;) { + if (s_pos >= length) + /* End of search string. */ + return text_ptr - text; + + if (text_ptr + s_pos >= limit_ptr) { + /* Off the end of the text. */ + if (state->partial_side == RE_PARTIAL_RIGHT) { + /* Partial match. */ + *is_partial = TRUE; + return text_ptr - text; + } + + return -1; + + } + + if (!same_char_ign(encoding, locale_info, text_ptr[s_pos], + values[s_pos])) + break; + + ++s_pos; + } + } + + ++text_ptr; + } + text_pos = text_ptr - text; + break; + } + case 2: + { + Py_UCS2* text = (Py_UCS2*)state->text; + Py_UCS2* text_ptr = text + text_pos; + Py_UCS2* limit_ptr = text + limit; + + while (text_ptr < limit_ptr) { + if (any_case(text_ptr[0], case_count, cases)) { + Py_ssize_t s_pos; + + s_pos = 1; + + for (;;) { + if (s_pos >= length) + /* End of search string. */ + return text_ptr - text; + + if (text_ptr + s_pos >= limit_ptr) { + /* Off the end of the text. */ + if (state->partial_side == RE_PARTIAL_RIGHT) { + /* Partial match. */ + *is_partial = TRUE; + return text_ptr - text; + } + + return -1; + + } + + if (!same_char_ign(encoding, locale_info, text_ptr[s_pos], + values[s_pos])) + break; + + ++s_pos; + } + } + + ++text_ptr; + } + text_pos = text_ptr - text; + break; + } + case 4: + { + Py_UCS4* text = (Py_UCS4*)state->text; + Py_UCS4* text_ptr = text + text_pos; + Py_UCS4* limit_ptr = text + limit; + + while (text_ptr < limit_ptr) { + if (any_case(text_ptr[0], case_count, cases)) { + Py_ssize_t s_pos; + + s_pos = 1; + + for (;;) { + if (s_pos >= length) + /* End of search string. */ + return text_ptr - text; + + if (text_ptr + s_pos >= limit_ptr) { + /* Off the end of the text. */ + if (state->partial_side == RE_PARTIAL_RIGHT) { + /* Partial match. */ + *is_partial = TRUE; + return text_ptr - text; + } + + return -1; + + } + + if (!same_char_ign(encoding, locale_info, text_ptr[s_pos], + values[s_pos])) + break; + + ++s_pos; + } + } + + ++text_ptr; + } + text_pos = text_ptr - text; + break; + } + } + + /* Off the end of the text. */ + if (state->partial_side == RE_PARTIAL_RIGHT) { + /* Partial match. */ + *is_partial = TRUE; + return text_pos; + } + + return -1; +} + +/* Performs a simple string search, backwards, ignoring case. */ +Py_LOCAL_INLINE(Py_ssize_t) simple_string_search_ign_rev(RE_State* state, + RE_Node* node, Py_ssize_t text_pos, Py_ssize_t limit, BOOL* is_partial) { + Py_ssize_t length; + RE_CODE* values; + RE_EncodingTable* encoding; + RE_LocaleInfo* locale_info; + Py_UCS4 cases[RE_MAX_CASES]; + int case_count; + + length = (Py_ssize_t)node->value_count; + values = node->values; + encoding = state->encoding; + locale_info = state->locale_info; + case_count = encoding->all_cases(locale_info, values[length - 1], cases); + + *is_partial = FALSE; + + switch (state->charsize) { + case 1: + { + Py_UCS1* text = (Py_UCS1*)state->text; + Py_UCS1* text_ptr = text + text_pos; + Py_UCS1* limit_ptr = text + limit; + + while (text_ptr > limit_ptr) { + if (any_case(text_ptr[-1], case_count, cases)) { + Py_ssize_t s_pos; + + s_pos = 1; + + for (;;) { + if (s_pos >= length) + /* End of search string. */ + return text_ptr - text; + + if (text_ptr - s_pos <= limit_ptr) { + /* Off the end of the text. */ + if (state->partial_side == RE_PARTIAL_LEFT) { + /* Partial match. */ + *is_partial = TRUE; + return text_ptr - text; + } + + return -1; + + } + + if (!same_char_ign(encoding, locale_info, text_ptr[- s_pos + - 1], values[length - s_pos - 1])) + break; + + ++s_pos; + } + } + + --text_ptr; + } + text_pos = text_ptr - text; + break; + } + case 2: + { + Py_UCS2* text = (Py_UCS2*)state->text; + Py_UCS2* text_ptr = text + text_pos; + Py_UCS2* limit_ptr = text + limit; + + while (text_ptr > limit_ptr) { + if (any_case(text_ptr[-1], case_count, cases)) { + Py_ssize_t s_pos; + + s_pos = 1; + + for (;;) { + if (s_pos >= length) + /* End of search string. */ + return text_ptr - text; + + if (text_ptr - s_pos <= limit_ptr) { + /* Off the end of the text. */ + if (state->partial_side == RE_PARTIAL_LEFT) { + /* Partial match. */ + *is_partial = TRUE; + return text_ptr - text; + } + + return -1; + + } + + if (!same_char_ign(encoding, locale_info, text_ptr[- s_pos + - 1], values[length - s_pos - 1])) + break; + + ++s_pos; + } + } + + --text_ptr; + } + text_pos = text_ptr - text; + break; + } + case 4: + { + Py_UCS4* text = (Py_UCS4*)state->text; + Py_UCS4* text_ptr = text + text_pos; + Py_UCS4* limit_ptr = text + limit; + + while (text_ptr > limit_ptr) { + if (any_case(text_ptr[-1], case_count, cases)) { + Py_ssize_t s_pos; + + s_pos = 1; + + for (;;) { + if (s_pos >= length) + /* End of search string. */ + return text_ptr - text; + + if (text_ptr - s_pos <= limit_ptr) { + /* Off the end of the text. */ + if (state->partial_side == RE_PARTIAL_LEFT) { + /* Partial match. */ + *is_partial = TRUE; + return text_ptr - text; + } + + return -1; + + } + + if (!same_char_ign(encoding, locale_info, text_ptr[- s_pos + - 1], values[length - s_pos - 1])) + break; + + ++s_pos; + } + } + + --text_ptr; + } + text_pos = text_ptr - text; + break; + } + } + + /* Off the end of the text. */ + if (state->partial_side == RE_PARTIAL_LEFT) { + /* Partial match. */ + *is_partial = TRUE; + return text_pos; + } + + return -1; +} + +/* Performs a simple string search, backwards. */ +Py_LOCAL_INLINE(Py_ssize_t) simple_string_search_rev(RE_State* state, RE_Node* + node, Py_ssize_t text_pos, Py_ssize_t limit, BOOL* is_partial) { + Py_ssize_t length; + RE_CODE* values; + Py_UCS4 check_char; + + length = (Py_ssize_t)node->value_count; + values = node->values; + check_char = values[length - 1]; + + *is_partial = FALSE; + + switch (state->charsize) { + case 1: + { + Py_UCS1* text = (Py_UCS1*)state->text; + Py_UCS1* text_ptr = text + text_pos; + Py_UCS1* limit_ptr = text + limit; + + while (text_ptr > limit_ptr) { + if (text_ptr[-1] == check_char) { + Py_ssize_t s_pos; + + s_pos = 1; + + for (;;) { + if (s_pos >= length) + /* End of search string. */ + return text_ptr - text; + + if (text_ptr - s_pos <= limit_ptr) { + /* Off the end of the text. */ + if (state->partial_side == RE_PARTIAL_LEFT) { + /* Partial match. */ + *is_partial = TRUE; + return text_ptr - text; + } + + return -1; + + } + + if (!same_char(text_ptr[- s_pos - 1], values[length - s_pos + - 1])) + break; + + ++s_pos; + } + } + + --text_ptr; + } + text_pos = text_ptr - text; + break; + } + case 2: + { + Py_UCS2* text = (Py_UCS2*)state->text; + Py_UCS2* text_ptr = text + text_pos; + Py_UCS2* limit_ptr = text + limit; + + while (text_ptr > limit_ptr) { + if (text_ptr[-1] == check_char) { + Py_ssize_t s_pos; + + s_pos = 1; + + for (;;) { + if (s_pos >= length) + /* End of search string. */ + return text_ptr - text; + + if (text_ptr - s_pos <= limit_ptr) { + /* Off the end of the text. */ + if (state->partial_side == RE_PARTIAL_LEFT) { + /* Partial match. */ + *is_partial = TRUE; + return text_ptr - text; + } + + return -1; + + } + + if (!same_char(text_ptr[- s_pos - 1], values[length - s_pos + - 1])) + break; + + ++s_pos; + } + } + + --text_ptr; + } + text_pos = text_ptr - text; + break; + } + case 4: + { + Py_UCS4* text = (Py_UCS4*)state->text; + Py_UCS4* text_ptr = text + text_pos; + Py_UCS4* limit_ptr = text + limit; + + while (text_ptr > limit_ptr) { + if (text_ptr[-1] == check_char) { + Py_ssize_t s_pos; + + s_pos = 1; + + for (;;) { + if (s_pos >= length) + /* End of search string. */ + return text_ptr - text; + + if (text_ptr - s_pos <= limit_ptr) { + /* Off the end of the text. */ + if (state->partial_side == RE_PARTIAL_LEFT) { + /* Partial match. */ + *is_partial = TRUE; + return text_ptr - text; + } + + return -1; + + } + + if (!same_char(text_ptr[- s_pos - 1], values[length - s_pos + - 1])) + break; + + ++s_pos; + } + } + + --text_ptr; + } + text_pos = text_ptr - text; + break; + } + } + + /* Off the end of the text. */ + if (state->partial_side == RE_PARTIAL_LEFT) { + /* Partial match. */ + *is_partial = TRUE; + return text_pos; + } + + return -1; +} + +/* Performs a Boyer-Moore fast string search. */ +Py_LOCAL_INLINE(Py_ssize_t) fast_string_search(RE_State* state, RE_Node* node, + Py_ssize_t text_pos, Py_ssize_t limit) { + void* text; + Py_ssize_t length; + RE_CODE* values; + Py_ssize_t* bad_character_offset; + Py_ssize_t* good_suffix_offset; + Py_ssize_t last_pos; + Py_UCS4 check_char; + + text = state->text; + length = (Py_ssize_t)node->value_count; + values = node->values; + good_suffix_offset = node->string.good_suffix_offset; + bad_character_offset = node->string.bad_character_offset; + last_pos = length - 1; + check_char = values[last_pos]; + limit -= length; + + switch (state->charsize) { + case 1: + { + Py_UCS1* text_ptr; + Py_UCS1* limit_ptr; + + text_ptr = (Py_UCS1*)text + text_pos; + limit_ptr = (Py_UCS1*)text + limit; + + while (text_ptr <= limit_ptr) { + Py_UCS4 ch; + + ch = text_ptr[last_pos]; + if (ch == check_char) { + Py_ssize_t pos; + + pos = last_pos - 1; + while (pos >= 0 && same_char(text_ptr[pos], values[pos])) + --pos; + + if (pos < 0) + return text_ptr - (Py_UCS1*)text; + + text_ptr += good_suffix_offset[pos]; + } else + text_ptr += bad_character_offset[ch & 0xFF]; + } + break; + } + case 2: + { + Py_UCS2* text_ptr; + Py_UCS2* limit_ptr; + + text_ptr = (Py_UCS2*)text + text_pos; + limit_ptr = (Py_UCS2*)text + limit; + + while (text_ptr <= limit_ptr) { + Py_UCS4 ch; + + ch = text_ptr[last_pos]; + if (ch == check_char) { + Py_ssize_t pos; + + pos = last_pos - 1; + while (pos >= 0 && same_char(text_ptr[pos], values[pos])) + --pos; + + if (pos < 0) + return text_ptr - (Py_UCS2*)text; + + text_ptr += good_suffix_offset[pos]; + } else + text_ptr += bad_character_offset[ch & 0xFF]; + } + break; + } + case 4: + { + Py_UCS4* text_ptr; + Py_UCS4* limit_ptr; + + text_ptr = (Py_UCS4*)text + text_pos; + limit_ptr = (Py_UCS4*)text + limit; + + while (text_ptr <= limit_ptr) { + Py_UCS4 ch; + + ch = text_ptr[last_pos]; + if (ch == check_char) { + Py_ssize_t pos; + + pos = last_pos - 1; + while (pos >= 0 && same_char(text_ptr[pos], values[pos])) + --pos; + + if (pos < 0) + return text_ptr - (Py_UCS4*)text; + + text_ptr += good_suffix_offset[pos]; + } else + text_ptr += bad_character_offset[ch & 0xFF]; + } + break; + } + } + + return -1; +} + +/* Performs a Boyer-Moore fast string search, ignoring case. */ +Py_LOCAL_INLINE(Py_ssize_t) fast_string_search_ign(RE_State* state, RE_Node* + node, Py_ssize_t text_pos, Py_ssize_t limit) { + RE_EncodingTable* encoding; + RE_LocaleInfo* locale_info; + void* text; + Py_ssize_t length; + RE_CODE* values; + Py_ssize_t* bad_character_offset; + Py_ssize_t* good_suffix_offset; + Py_ssize_t last_pos; + Py_UCS4 cases[RE_MAX_CASES]; + int case_count; + + encoding = state->encoding; + locale_info = state->locale_info; + text = state->text; + length = (Py_ssize_t)node->value_count; + values = node->values; + good_suffix_offset = node->string.good_suffix_offset; + bad_character_offset = node->string.bad_character_offset; + last_pos = length - 1; + case_count = encoding->all_cases(locale_info, values[last_pos], cases); + limit -= length; + + switch (state->charsize) { + case 1: + { + Py_UCS1* text_ptr; + Py_UCS1* limit_ptr; + + text_ptr = (Py_UCS1*)text + text_pos; + limit_ptr = (Py_UCS1*)text + limit; + + while (text_ptr <= limit_ptr) { + Py_UCS4 ch; + + ch = text_ptr[last_pos]; + if (any_case(ch, case_count, cases)) { + Py_ssize_t pos; + + pos = last_pos - 1; + while (pos >= 0 && same_char_ign(encoding, locale_info, + text_ptr[pos], values[pos])) + --pos; + + if (pos < 0) + return text_ptr - (Py_UCS1*)text; + + text_ptr += good_suffix_offset[pos]; + } else + text_ptr += bad_character_offset[ch & 0xFF]; + } + break; + } + case 2: + { + Py_UCS2* text_ptr; + Py_UCS2* limit_ptr; + + text_ptr = (Py_UCS2*)text + text_pos; + limit_ptr = (Py_UCS2*)text + limit; + + while (text_ptr <= limit_ptr) { + Py_UCS4 ch; + + ch = text_ptr[last_pos]; + if (any_case(ch, case_count, cases)) { + Py_ssize_t pos; + + pos = last_pos - 1; + while (pos >= 0 && same_char_ign(encoding, locale_info, + text_ptr[pos], values[pos])) + --pos; + + if (pos < 0) + return text_ptr - (Py_UCS2*)text; + + text_ptr += good_suffix_offset[pos]; + } else + text_ptr += bad_character_offset[ch & 0xFF]; + } + break; + } + case 4: + { + Py_UCS4* text_ptr; + Py_UCS4* limit_ptr; + + text_ptr = (Py_UCS4*)text + text_pos; + limit_ptr = (Py_UCS4*)text + limit; + + while (text_ptr <= limit_ptr) { + Py_UCS4 ch; + + ch = text_ptr[last_pos]; + if (any_case(ch, case_count, cases)) { + Py_ssize_t pos; + + pos = last_pos - 1; + while (pos >= 0 && same_char_ign(encoding, locale_info, + text_ptr[pos], values[pos])) + --pos; + + if (pos < 0) + return text_ptr - (Py_UCS4*)text; + + text_ptr += good_suffix_offset[pos]; + } else + text_ptr += bad_character_offset[ch & 0xFF]; + } + break; + } + } + + return -1; +} + +/* Performs a Boyer-Moore fast string search, backwards, ignoring case. */ +Py_LOCAL_INLINE(Py_ssize_t) fast_string_search_ign_rev(RE_State* state, + RE_Node* node, Py_ssize_t text_pos, Py_ssize_t limit) { + RE_EncodingTable* encoding; + RE_LocaleInfo* locale_info; + void* text; + Py_ssize_t length; + RE_CODE* values; + Py_ssize_t* bad_character_offset; + Py_ssize_t* good_suffix_offset; + Py_UCS4 cases[RE_MAX_CASES]; + int case_count; + + encoding = state->encoding; + locale_info = state->locale_info; + text = state->text; + length = (Py_ssize_t)node->value_count; + values = node->values; + good_suffix_offset = node->string.good_suffix_offset; + bad_character_offset = node->string.bad_character_offset; + case_count = encoding->all_cases(locale_info, values[0], cases); + text_pos -= length; + + switch (state->charsize) { + case 1: + { + Py_UCS1* text_ptr; + Py_UCS1* limit_ptr; + + text_ptr = (Py_UCS1*)text + text_pos; + limit_ptr = (Py_UCS1*)text + limit; + + while (text_ptr >= limit_ptr) { + Py_UCS4 ch; + + ch = text_ptr[0]; + if (any_case(ch, case_count, cases)) { + Py_ssize_t pos; + + pos = 1; + while (pos < length && same_char_ign(encoding, locale_info, + text_ptr[pos], values[pos])) + ++pos; + + if (pos >= length) + return text_ptr - (Py_UCS1*)text + length; + + text_ptr += good_suffix_offset[pos]; + } else + text_ptr += bad_character_offset[ch & 0xFF]; + } + break; + } + case 2: + { + Py_UCS2* text_ptr; + Py_UCS2* limit_ptr; + + text_ptr = (Py_UCS2*)text + text_pos; + limit_ptr = (Py_UCS2*)text + limit; + + while (text_ptr >= limit_ptr) { + Py_UCS4 ch; + + ch = text_ptr[0]; + if (any_case(ch, case_count, cases)) { + Py_ssize_t pos; + + pos = 1; + while (pos < length && same_char_ign(encoding, locale_info, + text_ptr[pos], values[pos])) + ++pos; + + if (pos >= length) + return text_ptr - (Py_UCS2*)text + length; + + text_ptr += good_suffix_offset[pos]; + } else + text_ptr += bad_character_offset[ch & 0xFF]; + } + break; + } + case 4: + { + Py_UCS4* text_ptr; + Py_UCS4* limit_ptr; + + text_ptr = (Py_UCS4*)text + text_pos; + limit_ptr = (Py_UCS4*)text + limit; + + while (text_ptr >= limit_ptr) { + Py_UCS4 ch; + + ch = text_ptr[0]; + if (any_case(ch, case_count, cases)) { + Py_ssize_t pos; + + pos = 1; + while (pos < length && same_char_ign(encoding, locale_info, + text_ptr[pos], values[pos])) + ++pos; + + if (pos >= length) + return text_ptr - (Py_UCS4*)text + length; + + text_ptr += good_suffix_offset[pos]; + } else + text_ptr += bad_character_offset[ch & 0xFF]; + } + break; + } + } + + return -1; +} + +/* Performs a Boyer-Moore fast string search, backwards. */ +Py_LOCAL_INLINE(Py_ssize_t) fast_string_search_rev(RE_State* state, RE_Node* + node, Py_ssize_t text_pos, Py_ssize_t limit) { + void* text; + Py_ssize_t length; + RE_CODE* values; + Py_ssize_t* bad_character_offset; + Py_ssize_t* good_suffix_offset; + Py_UCS4 check_char; + + text = state->text; + length = (Py_ssize_t)node->value_count; + values = node->values; + good_suffix_offset = node->string.good_suffix_offset; + bad_character_offset = node->string.bad_character_offset; + check_char = values[0]; + text_pos -= length; + + switch (state->charsize) { + case 1: + { + Py_UCS1* text_ptr; + Py_UCS1* limit_ptr; + + text_ptr = (Py_UCS1*)text + text_pos; + limit_ptr = (Py_UCS1*)text + limit; + + while (text_ptr >= limit_ptr) { + Py_UCS4 ch; + + ch = text_ptr[0]; + if (ch == check_char) { + Py_ssize_t pos; + + pos = 1; + while (pos < length && same_char(text_ptr[pos], values[pos])) + ++pos; + + if (pos >= length) + return text_ptr - (Py_UCS1*)text + length; + + text_ptr += good_suffix_offset[pos]; + } else + text_ptr += bad_character_offset[ch & 0xFF]; + } + break; + } + case 2: + { + Py_UCS2* text_ptr; + Py_UCS2* limit_ptr; + + text_ptr = (Py_UCS2*)text + text_pos; + limit_ptr = (Py_UCS2*)text + limit; + + while (text_ptr >= limit_ptr) { + Py_UCS4 ch; + + ch = text_ptr[0]; + if (ch == check_char) { + Py_ssize_t pos; + + pos = 1; + while (pos < length && same_char(text_ptr[pos], values[pos])) + ++pos; + + if (pos >= length) + return text_ptr - (Py_UCS2*)text + length; + + text_ptr += good_suffix_offset[pos]; + } else + text_ptr += bad_character_offset[ch & 0xFF]; + } + break; + } + case 4: + { + Py_UCS4* text_ptr; + Py_UCS4* limit_ptr; + + text_ptr = (Py_UCS4*)text + text_pos; + limit_ptr = (Py_UCS4*)text + limit; + + while (text_ptr >= limit_ptr) { + Py_UCS4 ch; + + ch = text_ptr[0]; + if (ch == check_char) { + Py_ssize_t pos; + + pos = 1; + while (pos < length && same_char(text_ptr[pos], values[pos])) + ++pos; + + if (pos >= length) + return text_ptr - (Py_UCS4*)text + length; + + text_ptr += good_suffix_offset[pos]; + } else + text_ptr += bad_character_offset[ch & 0xFF]; + } + break; + } + } + + return -1; +} + +/* Builds the tables for a Boyer-Moore fast string search. */ +Py_LOCAL_INLINE(BOOL) build_fast_tables(RE_State* state, RE_Node* node, BOOL + ignore) { + Py_ssize_t length; + RE_CODE* values; + Py_ssize_t* bad; + Py_ssize_t* good; + Py_UCS4 ch; + Py_ssize_t last_pos; + Py_ssize_t pos; + BOOL (*is_same_char)(RE_EncodingTable* encoding, RE_LocaleInfo* + locale_info, Py_UCS4 ch1, Py_UCS4 ch2); + Py_ssize_t suffix_len; + BOOL saved_start; + Py_ssize_t s; + Py_ssize_t i; + Py_ssize_t s_start; + Py_UCS4 codepoints[RE_MAX_CASES]; + + length = (Py_ssize_t)node->value_count; + + if (length < RE_MIN_FAST_LENGTH) + return TRUE; + + values = node->values; + bad = (Py_ssize_t*)re_alloc(256 * sizeof(bad[0])); + good = (Py_ssize_t*)re_alloc((size_t)length * sizeof(good[0])); + + if (!bad || !good) { + re_dealloc(bad); + re_dealloc(good); + + return FALSE; + } + + for (ch = 0; ch < 0x100; ch++) + bad[ch] = length; + + last_pos = length - 1; + + for (pos = 0; pos < last_pos; pos++) { + Py_ssize_t offset; + + offset = last_pos - pos; + ch = values[pos]; + if (ignore) { + int count; + int c; + + count = state->encoding->all_cases(state->locale_info, ch, + codepoints); + + for (c = 0; c < count; c++) + bad[codepoints[c] & 0xFF] = offset; + } else + bad[ch & 0xFF] = offset; + } + + is_same_char = ignore ? same_char_ign_wrapper : same_char_wrapper; + + suffix_len = 2; + pos = length - suffix_len; + saved_start = FALSE; + s = pos - 1; + i = suffix_len - 1; + s_start = s; + + while (pos >= 0) { + /* Look for another occurrence of the suffix. */ + while (i > 0) { + /* Have we dropped off the end of the string? */ + if (s + i < 0) + break; + + if (is_same_char(state->encoding, state->locale_info, values[s + + i], values[pos + i])) + /* It still matches. */ + --i; + else { + /* Start again further along. */ + --s; + i = suffix_len - 1; + } + } + + if (s >= 0 && is_same_char(state->encoding, state->locale_info, + values[s], values[pos])) { + /* We haven't dropped off the end of the string, and the suffix has + * matched this far, so this is a good starting point for the next + * iteration. + */ + --s; + if (!saved_start) { + s_start = s; + saved_start = TRUE; + } + } else { + /* Calculate the suffix offset. */ + good[pos] = pos - s; + + /* Extend the suffix and start searching for _this_ one. */ + --pos; + ++suffix_len; + + /* Where's a good place to start searching? */ + if (saved_start) { + s = s_start; + saved_start = FALSE; + } else + --s; + + /* Can we short-circuit the searching? */ + if (s < 0) + break; + } + + i = suffix_len - 1; + } + + /* Fill-in any remaining entries. */ + while (pos >= 0) { + good[pos] = pos - s; + --pos; + --s; + } + + node->string.bad_character_offset = bad; + node->string.good_suffix_offset = good; + + return TRUE; +} + +/* Builds the tables for a Boyer-Moore fast string search, backwards. */ +Py_LOCAL_INLINE(BOOL) build_fast_tables_rev(RE_State* state, RE_Node* node, + BOOL ignore) { + Py_ssize_t length; + RE_CODE* values; + Py_ssize_t* bad; + Py_ssize_t* good; + Py_UCS4 ch; + Py_ssize_t last_pos; + Py_ssize_t pos; + BOOL (*is_same_char)(RE_EncodingTable* encoding, RE_LocaleInfo* + locale_info, Py_UCS4 ch1, Py_UCS4 ch2); + Py_ssize_t suffix_len; + BOOL saved_start; + Py_ssize_t s; + Py_ssize_t i; + Py_ssize_t s_start; + Py_UCS4 codepoints[RE_MAX_CASES]; + + length = (Py_ssize_t)node->value_count; + + if (length < RE_MIN_FAST_LENGTH) + return TRUE; + + values = node->values; + bad = (Py_ssize_t*)re_alloc(256 * sizeof(bad[0])); + good = (Py_ssize_t*)re_alloc((size_t)length * sizeof(good[0])); + + if (!bad || !good) { + re_dealloc(bad); + re_dealloc(good); + + return FALSE; + } + + for (ch = 0; ch < 0x100; ch++) + bad[ch] = -length; + + last_pos = length - 1; + + for (pos = last_pos; pos > 0; pos--) { + Py_ssize_t offset; + + offset = -pos; + ch = values[pos]; + if (ignore) { + int count; + int c; + + count = state->encoding->all_cases(state->locale_info, ch, + codepoints); + + for (c = 0; c < count; c++) + bad[codepoints[c] & 0xFF] = offset; + } else + bad[ch & 0xFF] = offset; + } + + is_same_char = ignore ? same_char_ign_wrapper : same_char_wrapper; + + suffix_len = 2; + pos = suffix_len - 1; + saved_start = FALSE; + s = pos + 1; + i = suffix_len - 1; + s_start = s; + + while (pos < length) { + /* Look for another occurrence of the suffix. */ + while (i > 0) { + /* Have we dropped off the end of the string? */ + if (s - i >= length) + break; + + if (is_same_char(state->encoding, state->locale_info, values[s - + i], values[pos - i])) + /* It still matches. */ + --i; + else { + /* Start again further along. */ + ++s; + i = suffix_len - 1; + } + } + + if (s < length && is_same_char(state->encoding, state->locale_info, + values[s], values[pos])) { + /* We haven't dropped off the end of the string, and the suffix has + * matched this far, so this is a good starting point for the next + * iteration. + */ + ++s; + if (!saved_start) { + s_start = s; + saved_start = TRUE; + } + } else { + /* Calculate the suffix offset. */ + good[pos] = pos - s; + + /* Extend the suffix and start searching for _this_ one. */ + ++pos; + ++suffix_len; + + /* Where's a good place to start searching? */ + if (saved_start) { + s = s_start; + saved_start = FALSE; + } else + ++s; + + /* Can we short-circuit the searching? */ + if (s >= length) + break; + } + + i = suffix_len - 1; + } + + /* Fill-in any remaining entries. */ + while (pos < length) { + good[pos] = pos - s; + ++pos; + ++s; + } + + node->string.bad_character_offset = bad; + node->string.good_suffix_offset = good; + + return TRUE; +} + +/* Performs a string search. */ +Py_LOCAL_INLINE(Py_ssize_t) string_search(RE_State* state, RE_Node* node, + Py_ssize_t text_pos, Py_ssize_t limit, BOOL try_fast, BOOL* is_partial) { + Py_ssize_t found_pos; + + *is_partial = FALSE; + + /* Has the node been initialised for fast searching, if necessary? */ + if (try_fast && !(node->status & RE_STATUS_FAST_INIT)) { + /* Ideally the pattern should immutable and shareable across threads. + * Internally, however, it isn't. For safety we need to hold the GIL. + */ + acquire_GIL(state); + + /* Double-check because of multithreading. */ + if (!(node->status & RE_STATUS_FAST_INIT)) { + build_fast_tables(state, node, FALSE); + node->status |= RE_STATUS_FAST_INIT; + } + + release_GIL(state); + } + + if (try_fast && node->string.bad_character_offset) { + /* Start with a fast search. This will find the string if it's complete + * (i.e. not truncated). + */ + found_pos = fast_string_search(state, node, text_pos, limit); + if (found_pos < 0 && state->partial_side == RE_PARTIAL_RIGHT) + /* We didn't find the string, but it could've been truncated, so + * try again, starting close to the end. + */ + found_pos = simple_string_search(state, node, limit - + (Py_ssize_t)(node->value_count - 1), limit, is_partial); + } else + found_pos = simple_string_search(state, node, text_pos, limit, + is_partial); + + return found_pos; +} + +/* Performs a string search, ignoring case. */ +Py_LOCAL_INLINE(Py_ssize_t) string_search_fld(RE_State* state, RE_Node* node, + Py_ssize_t text_pos, Py_ssize_t limit, Py_ssize_t* new_pos, BOOL* is_partial) + { + RE_EncodingTable* encoding; + RE_LocaleInfo* locale_info; + int (*full_case_fold)(RE_LocaleInfo* locale_info, Py_UCS4 ch, Py_UCS4* + folded); + Py_UCS4 (*char_at)(void* text, Py_ssize_t pos); + void* text; + RE_CODE* values; + Py_ssize_t start_pos; + int f_pos; + int folded_len; + Py_ssize_t length; + Py_ssize_t s_pos; + Py_UCS4 folded[RE_MAX_FOLDED]; + + encoding = state->encoding; + locale_info = state->locale_info; + full_case_fold = encoding->full_case_fold; + char_at = state->char_at; + text = state->text; + + values = node->values; + start_pos = text_pos; + f_pos = 0; + folded_len = 0; + length = (Py_ssize_t)node->value_count; + s_pos = 0; + + *is_partial = FALSE; + + while (s_pos < length || f_pos < folded_len) { + if (f_pos >= folded_len) { + /* Fetch and casefold another character. */ + if (text_pos >= limit) { + if (text_pos >= state->text_end && state->partial_side == + RE_PARTIAL_RIGHT) { + *is_partial = TRUE; + return start_pos; + } + + return -1; + } + + folded_len = full_case_fold(locale_info, char_at(text, text_pos), + folded); + f_pos = 0; + } + + if (s_pos < length && same_char_ign_turkic(encoding, locale_info, + values[s_pos], folded[f_pos])) { + ++s_pos; + ++f_pos; + + if (f_pos >= folded_len) + ++text_pos; + } else { + ++start_pos; + text_pos = start_pos; + f_pos = 0; + folded_len = 0; + s_pos = 0; + } + } + + /* We found the string. */ + if (new_pos) + *new_pos = text_pos; + + return start_pos; +} + +/* Performs a string search, backwards, ignoring case. */ +Py_LOCAL_INLINE(Py_ssize_t) string_search_fld_rev(RE_State* state, RE_Node* + node, Py_ssize_t text_pos, Py_ssize_t limit, Py_ssize_t* new_pos, BOOL* + is_partial) { + RE_EncodingTable* encoding; + RE_LocaleInfo* locale_info; + int (*full_case_fold)(RE_LocaleInfo* locale_info, Py_UCS4 ch, Py_UCS4* + folded); + Py_UCS4 (*char_at)(void* text, Py_ssize_t pos); + void* text; + RE_CODE* values; + Py_ssize_t start_pos; + int f_pos; + int folded_len; + Py_ssize_t length; + Py_ssize_t s_pos; + Py_UCS4 folded[RE_MAX_FOLDED]; + + encoding = state->encoding; + locale_info = state->locale_info; + full_case_fold = encoding->full_case_fold; + char_at = state->char_at; + text = state->text; + + values = node->values; + start_pos = text_pos; + f_pos = 0; + folded_len = 0; + length = (Py_ssize_t)node->value_count; + s_pos = 0; + + *is_partial = FALSE; + + while (s_pos < length || f_pos < folded_len) { + if (f_pos >= folded_len) { + /* Fetch and casefold another character. */ + if (text_pos <= limit) { + if (text_pos <= state->text_start && state->partial_side == RE_PARTIAL_LEFT) { + *is_partial = TRUE; + return start_pos; + } + + return -1; + } + + folded_len = full_case_fold(locale_info, char_at(text, text_pos - + 1), folded); + f_pos = 0; + } + + if (s_pos < length && same_char_ign_turkic(encoding, locale_info, + values[length - s_pos - 1], folded[folded_len - f_pos - 1])) { + ++s_pos; + ++f_pos; + + if (f_pos >= folded_len) + --text_pos; + } else { + --start_pos; + text_pos = start_pos; + f_pos = 0; + folded_len = 0; + s_pos = 0; + } + } + + /* We found the string. */ + if (new_pos) + *new_pos = text_pos; + + return start_pos; +} + +/* Performs a string search, ignoring case. */ +Py_LOCAL_INLINE(Py_ssize_t) string_search_ign(RE_State* state, RE_Node* node, + Py_ssize_t text_pos, Py_ssize_t limit, BOOL try_fast, BOOL* is_partial) { + Py_ssize_t found_pos; + + *is_partial = FALSE; + + /* Has the node been initialised for fast searching, if necessary? */ + if (try_fast && !(node->status & RE_STATUS_FAST_INIT)) { + /* Ideally the pattern should immutable and shareable across threads. + * Internally, however, it isn't. For safety we need to hold the GIL. + */ + acquire_GIL(state); + + /* Double-check because of multithreading. */ + if (!(node->status & RE_STATUS_FAST_INIT)) { + build_fast_tables(state, node, TRUE); + node->status |= RE_STATUS_FAST_INIT; + } + + release_GIL(state); + } + + if (try_fast && node->string.bad_character_offset) { + /* Start with a fast search. This will find the string if it's complete + * (i.e. not truncated). + */ + found_pos = fast_string_search_ign(state, node, text_pos, limit); + if (found_pos < 0 && state->partial_side == RE_PARTIAL_RIGHT) + /* We didn't find the string, but it could've been truncated, so + * try again, starting close to the end. + */ + found_pos = simple_string_search_ign(state, node, limit - + (Py_ssize_t)(node->value_count - 1), limit, is_partial); + } else + found_pos = simple_string_search_ign(state, node, text_pos, limit, + is_partial); + + return found_pos; +} + +/* Performs a string search, backwards, ignoring case. */ +Py_LOCAL_INLINE(Py_ssize_t) string_search_ign_rev(RE_State* state, RE_Node* + node, Py_ssize_t text_pos, Py_ssize_t limit, BOOL try_fast, BOOL* is_partial) + { + Py_ssize_t found_pos; + + *is_partial = FALSE; + + /* Has the node been initialised for fast searching, if necessary? */ + if (try_fast && !(node->status & RE_STATUS_FAST_INIT)) { + /* Ideally the pattern should immutable and shareable across threads. + * Internally, however, it isn't. For safety we need to hold the GIL. + */ + acquire_GIL(state); + + /* Double-check because of multithreading. */ + if (!(node->status & RE_STATUS_FAST_INIT)) { + build_fast_tables_rev(state, node, TRUE); + node->status |= RE_STATUS_FAST_INIT; + } + + release_GIL(state); + } + + if (try_fast && node->string.bad_character_offset) { + /* Start with a fast search. This will find the string if it's complete + * (i.e. not truncated). + */ + found_pos = fast_string_search_ign_rev(state, node, text_pos, limit); + if (found_pos < 0 && state->partial_side == RE_PARTIAL_LEFT) + /* We didn't find the string, but it could've been truncated, so + * try again, starting close to the end. + */ + found_pos = simple_string_search_ign_rev(state, node, limit + + (Py_ssize_t)(node->value_count - 1), limit, is_partial); + } else + found_pos = simple_string_search_ign_rev(state, node, text_pos, limit, + is_partial); + + return found_pos; +} + +/* Performs a string search, backwards. */ +Py_LOCAL_INLINE(Py_ssize_t) string_search_rev(RE_State* state, RE_Node* node, + Py_ssize_t text_pos, Py_ssize_t limit, BOOL try_fast, BOOL* is_partial) { + Py_ssize_t found_pos; + + *is_partial = FALSE; + + /* Has the node been initialised for fast searching, if necessary? */ + if (try_fast && !(node->status & RE_STATUS_FAST_INIT)) { + /* Ideally the pattern should immutable and shareable across threads. + * Internally, however, it isn't. For safety we need to hold the GIL. + */ + acquire_GIL(state); + + /* Double-check because of multithreading. */ + if (!(node->status & RE_STATUS_FAST_INIT)) { + build_fast_tables_rev(state, node, FALSE); + node->status |= RE_STATUS_FAST_INIT; + } + + release_GIL(state); + } + + if (try_fast && node->string.bad_character_offset) { + /* Start with a fast search. This will find the string if it's complete + * (i.e. not truncated). + */ + found_pos = fast_string_search_rev(state, node, text_pos, limit); + if (found_pos < 0 && state->partial_side == RE_PARTIAL_LEFT) + /* We didn't find the string, but it could've been truncated, so + * try again, starting close to the end. + */ + found_pos = simple_string_search_rev(state, node, limit + + (Py_ssize_t)(node->value_count - 1), limit, is_partial); + } else + found_pos = simple_string_search_rev(state, node, text_pos, limit, + is_partial); + + return found_pos; +} + +/* Returns how many characters there could be before full case-folding. */ +Py_LOCAL_INLINE(Py_ssize_t) possible_unfolded_length(Py_ssize_t length) { + if (length == 0) + return 0; + + if (length < RE_MAX_FOLDED) + return 1; + + return length / RE_MAX_FOLDED; +} + +/* Checks whether there's any character except a newline at a position. */ +Py_LOCAL_INLINE(int) try_match_ANY(RE_State* state, RE_Node* node, Py_ssize_t + text_pos) { + if (text_pos >= state->text_end) { + if (state->partial_side == RE_PARTIAL_RIGHT) + return RE_ERROR_PARTIAL; + + return RE_ERROR_FAILURE; + } + + return bool_as_status(text_pos < state->slice_end && + matches_ANY(state->encoding, node, state->char_at(state->text, + text_pos))); +} + +/* Checks whether there's any character at all at a position. */ +Py_LOCAL_INLINE(int) try_match_ANY_ALL(RE_State* state, RE_Node* node, + Py_ssize_t text_pos) { + if (text_pos >= state->text_end) { + if (state->partial_side == RE_PARTIAL_RIGHT) + return RE_ERROR_PARTIAL; + + return RE_ERROR_FAILURE; + } + + return bool_as_status(text_pos < state->slice_end); +} + +/* Checks whether there's any character at all at a position, backwards. */ +Py_LOCAL_INLINE(int) try_match_ANY_ALL_REV(RE_State* state, RE_Node* node, + Py_ssize_t text_pos) { + if (text_pos <= state->text_start) { + if (state->partial_side == RE_PARTIAL_LEFT) + return RE_ERROR_PARTIAL; + + return RE_ERROR_FAILURE; + } + + return bool_as_status(text_pos > state->slice_start); +} + +/* Checks whether there's any character except a newline at a position, + * backwards. + */ +Py_LOCAL_INLINE(int) try_match_ANY_REV(RE_State* state, RE_Node* node, + Py_ssize_t text_pos) { + if (text_pos <= state->text_start) { + if (state->partial_side == RE_PARTIAL_LEFT) + return RE_ERROR_PARTIAL; + + return RE_ERROR_FAILURE; + } + + return bool_as_status(text_pos > state->slice_start && + matches_ANY(state->encoding, node, state->char_at(state->text, text_pos - + 1))); +} + +/* Checks whether there's any character except a line separator at a position. + */ +Py_LOCAL_INLINE(int) try_match_ANY_U(RE_State* state, RE_Node* node, Py_ssize_t + text_pos) { + if (text_pos >= state->text_end) { + if (state->partial_side == RE_PARTIAL_RIGHT) + return RE_ERROR_PARTIAL; + + return RE_ERROR_FAILURE; + } + + return bool_as_status(text_pos < state->slice_end && + matches_ANY_U(state->encoding, node, state->char_at(state->text, + text_pos))); +} + +/* Checks whether there's any character except a line separator at a position, + * backwards. + */ +Py_LOCAL_INLINE(int) try_match_ANY_U_REV(RE_State* state, RE_Node* node, + Py_ssize_t text_pos) { + if (text_pos <= state->text_start) { + if (state->partial_side == RE_PARTIAL_LEFT) + return RE_ERROR_PARTIAL; + + return RE_ERROR_FAILURE; + } + + return bool_as_status(text_pos > state->slice_start && + matches_ANY_U(state->encoding, node, state->char_at(state->text, text_pos + - 1))); +} + +/* Checks whether a position is on a word boundary. */ +Py_LOCAL_INLINE(int) try_match_BOUNDARY(RE_State* state, RE_Node* node, + Py_ssize_t text_pos) { + return bool_as_status(state->encoding->at_boundary(state, text_pos) == + node->match); +} + +/* Checks whether there's a character at a position. */ +Py_LOCAL_INLINE(int) try_match_CHARACTER(RE_State* state, RE_Node* node, + Py_ssize_t text_pos) { + if (text_pos >= state->text_end) { + if (state->partial_side == RE_PARTIAL_RIGHT) + return RE_ERROR_PARTIAL; + + return RE_ERROR_FAILURE; + } + + return bool_as_status(text_pos < state->slice_end && + matches_CHARACTER(state->encoding, state->locale_info, node, + state->char_at(state->text, text_pos)) == node->match); +} + +/* Checks whether there's a character at a position, ignoring case. */ +Py_LOCAL_INLINE(int) try_match_CHARACTER_IGN(RE_State* state, RE_Node* node, + Py_ssize_t text_pos) { + if (text_pos >= state->text_end) { + if (state->partial_side == RE_PARTIAL_RIGHT) + return RE_ERROR_PARTIAL; + + return RE_ERROR_FAILURE; + } + + return bool_as_status(text_pos < state->slice_end && + matches_CHARACTER_IGN(state->encoding, state->locale_info, node, + state->char_at(state->text, text_pos)) == node->match); +} + +/* Checks whether there's a character at a position, ignoring case, backwards. + */ +Py_LOCAL_INLINE(int) try_match_CHARACTER_IGN_REV(RE_State* state, RE_Node* + node, Py_ssize_t text_pos) { + if (text_pos <= state->text_start) { + if (state->partial_side == RE_PARTIAL_LEFT) + return RE_ERROR_PARTIAL; + + return RE_ERROR_FAILURE; + } + + return bool_as_status(text_pos > state->slice_start && + matches_CHARACTER_IGN(state->encoding, state->locale_info, node, + state->char_at(state->text, text_pos - 1)) == node->match); +} + +/* Checks whether there's a character at a position, backwards. */ +Py_LOCAL_INLINE(int) try_match_CHARACTER_REV(RE_State* state, RE_Node* node, + Py_ssize_t text_pos) { + if (text_pos <= state->text_start) { + if (state->partial_side == RE_PARTIAL_LEFT) + return RE_ERROR_PARTIAL; + + return RE_ERROR_FAILURE; + } + + return bool_as_status(text_pos > state->slice_start && + matches_CHARACTER(state->encoding, state->locale_info, node, + state->char_at(state->text, text_pos - 1)) == node->match); +} + +/* Checks whether a position is on a default word boundary. */ +Py_LOCAL_INLINE(int) try_match_DEFAULT_BOUNDARY(RE_State* state, RE_Node* node, + Py_ssize_t text_pos) { + return bool_as_status(state->encoding->at_default_boundary(state, text_pos) + == node->match); +} + +/* Checks whether a position is at the default end of a word. */ +Py_LOCAL_INLINE(int) try_match_DEFAULT_END_OF_WORD(RE_State* state, RE_Node* + node, Py_ssize_t text_pos) { + return bool_as_status(state->encoding->at_default_word_end(state, + text_pos)); +} + +/* Checks whether a position is at the default start of a word. */ +Py_LOCAL_INLINE(int) try_match_DEFAULT_START_OF_WORD(RE_State* state, RE_Node* + node, Py_ssize_t text_pos) { + return bool_as_status(state->encoding->at_default_word_start(state, + text_pos)); +} + +/* Checks whether a position is at the end of a line. */ +Py_LOCAL_INLINE(int) try_match_END_OF_LINE(RE_State* state, RE_Node* node, + Py_ssize_t text_pos) { + return bool_as_status(text_pos >= state->slice_end || + state->char_at(state->text, text_pos) == '\n'); +} + +/* Checks whether a position is at the end of a line. */ +Py_LOCAL_INLINE(int) try_match_END_OF_LINE_U(RE_State* state, RE_Node* node, + Py_ssize_t text_pos) { + return bool_as_status(state->encoding->at_line_end(state, text_pos)); +} + +/* Checks whether a position is at the end of the string. */ +Py_LOCAL_INLINE(int) try_match_END_OF_STRING(RE_State* state, RE_Node* node, + Py_ssize_t text_pos) { + return bool_as_status(text_pos >= state->text_end); +} + +/* Checks whether a position is at the end of a line or the string. */ +Py_LOCAL_INLINE(int) try_match_END_OF_STRING_LINE(RE_State* state, RE_Node* + node, Py_ssize_t text_pos) { + return bool_as_status(text_pos >= state->text_end || text_pos == + state->final_newline); +} + +/* Checks whether a position is at the end of the string. */ +Py_LOCAL_INLINE(int) try_match_END_OF_STRING_LINE_U(RE_State* state, RE_Node* + node, Py_ssize_t text_pos) { + return bool_as_status(text_pos >= state->text_end || text_pos == + state->final_line_sep); +} + +/* Checks whether a position is at the end of a word. */ +Py_LOCAL_INLINE(int) try_match_END_OF_WORD(RE_State* state, RE_Node* node, + Py_ssize_t text_pos) { + return bool_as_status(state->encoding->at_word_end(state, text_pos)); +} + +/* Checks whether a position is on a grapheme boundary. */ +Py_LOCAL_INLINE(int) try_match_GRAPHEME_BOUNDARY(RE_State* state, RE_Node* + node, Py_ssize_t text_pos) { + return bool_as_status(state->encoding->at_grapheme_boundary(state, + text_pos)); +} + +/* Checks whether there's a character with a certain property at a position. */ +Py_LOCAL_INLINE(int) try_match_PROPERTY(RE_State* state, RE_Node* node, + Py_ssize_t text_pos) { + if (text_pos >= state->text_end) { + if (state->partial_side == RE_PARTIAL_RIGHT) + return RE_ERROR_PARTIAL; + + return RE_ERROR_FAILURE; + } + + return bool_as_status(text_pos < state->slice_end && + matches_PROPERTY(state->encoding, state->locale_info, node, + state->char_at(state->text, text_pos)) == node->match); +} + +/* Checks whether there's a character with a certain property at a position, + * ignoring case. + */ +Py_LOCAL_INLINE(int) try_match_PROPERTY_IGN(RE_State* state, RE_Node* node, + Py_ssize_t text_pos) { + if (text_pos >= state->text_end) { + if (state->partial_side == RE_PARTIAL_RIGHT) + return RE_ERROR_PARTIAL; + + return RE_ERROR_FAILURE; + } + + return bool_as_status(text_pos < state->slice_end && + matches_PROPERTY_IGN(state->encoding, state->locale_info, node, + state->char_at(state->text, text_pos)) == node->match); +} + +/* Checks whether there's a character with a certain property at a position, + * ignoring case, backwards. + */ +Py_LOCAL_INLINE(int) try_match_PROPERTY_IGN_REV(RE_State* state, RE_Node* node, + Py_ssize_t text_pos) { + if (text_pos <= state->text_start) { + if (state->partial_side == RE_PARTIAL_LEFT) + return RE_ERROR_PARTIAL; + + return RE_ERROR_FAILURE; + } + + return bool_as_status(text_pos > state->slice_start && + matches_PROPERTY_IGN(state->encoding, state->locale_info, node, + state->char_at(state->text, text_pos - 1)) == node->match); +} + +/* Checks whether there's a character with a certain property at a position, + * backwards. + */ +Py_LOCAL_INLINE(int) try_match_PROPERTY_REV(RE_State* state, RE_Node* node, + Py_ssize_t text_pos) { + if (text_pos <= state->text_start) { + if (state->partial_side == RE_PARTIAL_LEFT) + return RE_ERROR_PARTIAL; + + return RE_ERROR_FAILURE; + } + + return bool_as_status(text_pos > state->slice_start && + matches_PROPERTY(state->encoding, state->locale_info, node, + state->char_at(state->text, text_pos - 1)) == node->match); +} + +/* Checks whether there's a character in a certain range at a position. */ +Py_LOCAL_INLINE(int) try_match_RANGE(RE_State* state, RE_Node* node, Py_ssize_t + text_pos) { + if (text_pos >= state->text_end) { + if (state->partial_side == RE_PARTIAL_RIGHT) + return RE_ERROR_PARTIAL; + + return RE_ERROR_FAILURE; + } + + return bool_as_status(text_pos < state->slice_end && + matches_RANGE(state->encoding, state->locale_info, node, + state->char_at(state->text, text_pos)) == node->match); +} + +/* Checks whether there's a character in a certain range at a position, + * ignoring case. + */ +Py_LOCAL_INLINE(int) try_match_RANGE_IGN(RE_State* state, RE_Node* node, + Py_ssize_t text_pos) { + if (text_pos >= state->text_end) { + if (state->partial_side == RE_PARTIAL_RIGHT) + return RE_ERROR_PARTIAL; + + return RE_ERROR_FAILURE; + } + + return bool_as_status(text_pos < state->slice_end && + matches_RANGE_IGN(state->encoding, state->locale_info, node, + state->char_at(state->text, text_pos)) == node->match); +} + +/* Checks whether there's a character in a certain range at a position, + * ignoring case, backwards. + */ +Py_LOCAL_INLINE(int) try_match_RANGE_IGN_REV(RE_State* state, RE_Node* node, + Py_ssize_t text_pos) { + if (text_pos <= state->text_start) { + if (state->partial_side == RE_PARTIAL_LEFT) + return RE_ERROR_PARTIAL; + + return RE_ERROR_FAILURE; + } + + return bool_as_status(text_pos > state->slice_start && + matches_RANGE_IGN(state->encoding, state->locale_info, node, + state->char_at(state->text, text_pos - 1)) == node->match); +} + +/* Checks whether there's a character in a certain range at a position, + * backwards. + */ +Py_LOCAL_INLINE(int) try_match_RANGE_REV(RE_State* state, RE_Node* node, + Py_ssize_t text_pos) { + if (text_pos <= state->text_start) { + if (state->partial_side == RE_PARTIAL_LEFT) + return RE_ERROR_PARTIAL; + + return RE_ERROR_FAILURE; + } + + return bool_as_status(text_pos > state->slice_start && + matches_RANGE(state->encoding, state->locale_info, node, + state->char_at(state->text, text_pos - 1)) == node->match); +} + +/* Checks whether a position is at the search anchor. */ +Py_LOCAL_INLINE(int) try_match_SEARCH_ANCHOR(RE_State* state, RE_Node* node, + Py_ssize_t text_pos) { + return bool_as_status(text_pos == state->search_anchor); +} + +/* Checks whether there's a character in a certain set at a position. */ +Py_LOCAL_INLINE(int) try_match_SET(RE_State* state, RE_Node* node, Py_ssize_t + text_pos) { + if (text_pos >= state->text_end) { + if (state->partial_side == RE_PARTIAL_RIGHT) + return RE_ERROR_PARTIAL; + + return RE_ERROR_FAILURE; + } + + return bool_as_status(text_pos < state->slice_end && + matches_SET(state->encoding, state->locale_info, node, + state->char_at(state->text, text_pos)) == node->match); +} + +/* Checks whether there's a character in a certain set at a position, ignoring + * case. + */ +Py_LOCAL_INLINE(int) try_match_SET_IGN(RE_State* state, RE_Node* node, + Py_ssize_t text_pos) { + if (text_pos >= state->text_end) { + if (state->partial_side == RE_PARTIAL_RIGHT) + return RE_ERROR_PARTIAL; + + return RE_ERROR_FAILURE; + } + + return bool_as_status(text_pos < state->slice_end && + matches_SET_IGN(state->encoding, state->locale_info, node, + state->char_at(state->text, text_pos)) == node->match); +} + +/* Checks whether there's a character in a certain set at a position, ignoring + * case, backwards. + */ +Py_LOCAL_INLINE(int) try_match_SET_IGN_REV(RE_State* state, RE_Node* node, + Py_ssize_t text_pos) { + if (text_pos <= state->text_start) { + if (state->partial_side == RE_PARTIAL_LEFT) + return RE_ERROR_PARTIAL; + + return RE_ERROR_FAILURE; + } + + return bool_as_status(text_pos > state->slice_start && + matches_SET_IGN(state->encoding, state->locale_info, node, + state->char_at(state->text, text_pos - 1)) == node->match); +} + +/* Checks whether there's a character in a certain set at a position, + * backwards. + */ +Py_LOCAL_INLINE(int) try_match_SET_REV(RE_State* state, RE_Node* node, + Py_ssize_t text_pos) { + if (text_pos <= state->text_start) { + if (state->partial_side == RE_PARTIAL_LEFT) + return RE_ERROR_PARTIAL; + + return RE_ERROR_FAILURE; + } + + return bool_as_status(text_pos > state->slice_start && + matches_SET(state->encoding, state->locale_info, node, + state->char_at(state->text, text_pos - 1)) == node->match); +} + +/* Checks whether a position is at the start of a line. */ +Py_LOCAL_INLINE(int) try_match_START_OF_LINE(RE_State* state, RE_Node* node, + Py_ssize_t text_pos) { + return bool_as_status(text_pos <= state->text_start || state->char_at(state->text, text_pos + - 1) == '\n'); +} + +/* Checks whether a position is at the start of a line. */ +Py_LOCAL_INLINE(int) try_match_START_OF_LINE_U(RE_State* state, RE_Node* node, + Py_ssize_t text_pos) { + return bool_as_status(state->encoding->at_line_start(state, text_pos)); +} + +/* Checks whether a position is at the start of the string. */ +Py_LOCAL_INLINE(int) try_match_START_OF_STRING(RE_State* state, RE_Node* node, + Py_ssize_t text_pos) { + return bool_as_status(text_pos <= state->text_start); +} + +/* Checks whether a position is at the start of a word. */ +Py_LOCAL_INLINE(int) try_match_START_OF_WORD(RE_State* state, RE_Node* node, + Py_ssize_t text_pos) { + return bool_as_status(state->encoding->at_word_start(state, text_pos)); +} + +/* Checks whether there's a certain string at a position. */ +Py_LOCAL_INLINE(int) try_match_STRING(RE_State* state, RE_NextNode* next, + RE_Node* node, Py_ssize_t text_pos, RE_Position* next_position) { + Py_ssize_t length; + Py_UCS4 (*char_at)(void* text, Py_ssize_t pos); + RE_CODE* values; + Py_ssize_t s_pos; + + length = (Py_ssize_t)node->value_count; + char_at = state->char_at; + values = node->values; + + for (s_pos = 0; s_pos < length; s_pos++) { + if (text_pos + s_pos >= state->slice_end) { + if (state->partial_side == RE_PARTIAL_RIGHT) { + next_position->text_pos = text_pos; + return RE_ERROR_PARTIAL; + } + + return RE_ERROR_FAILURE; + } + + if (!same_char(char_at(state->text, text_pos + s_pos), values[s_pos])) + return RE_ERROR_FAILURE; + } + + next_position->node = next->match_next; + next_position->text_pos = text_pos + next->match_step; + + return RE_ERROR_SUCCESS; +} + +/* Checks whether there's a certain string at a position, ignoring case. */ +Py_LOCAL_INLINE(int) try_match_STRING_FLD(RE_State* state, RE_NextNode* next, + RE_Node* node, Py_ssize_t text_pos, RE_Position* next_position) { + Py_ssize_t length; + Py_UCS4 (*char_at)(void* text, Py_ssize_t pos); + RE_EncodingTable* encoding; + RE_LocaleInfo* locale_info; + int (*full_case_fold)(RE_LocaleInfo* locale_info, Py_UCS4 ch, Py_UCS4* + folded); + Py_ssize_t s_pos; + RE_CODE* values; + int folded_len; + int f_pos; + Py_ssize_t start_pos; + Py_UCS4 folded[RE_MAX_FOLDED]; + + length = (Py_ssize_t)node->value_count; + char_at = state->char_at; + encoding = state->encoding; + locale_info = state->locale_info; + full_case_fold = encoding->full_case_fold; + + s_pos = 0; + values = node->values; + folded_len = 0; + f_pos = 0; + start_pos = text_pos; + + while (s_pos < length) { + if (f_pos >= folded_len) { + /* Fetch and casefold another character. */ + if (text_pos >= state->slice_end) { + if (state->partial_side == RE_PARTIAL_RIGHT) { + if (next->match_step == 0) + next_position->text_pos = start_pos; + else + next_position->text_pos = text_pos; + return RE_ERROR_PARTIAL; + } + + return RE_ERROR_FAILURE; + } + + folded_len = full_case_fold(locale_info, char_at(state->text, + text_pos), folded); + f_pos = 0; + } + + if (!same_char_ign(encoding, locale_info, values[s_pos], + folded[f_pos])) + return RE_ERROR_FAILURE; + + ++s_pos; + ++f_pos; + + if (f_pos >= folded_len) + ++text_pos; + } + + if (f_pos < folded_len) + return RE_ERROR_FAILURE; + + next_position->node = next->match_next; + if (next->match_step == 0) + next_position->text_pos = start_pos; + else + next_position->text_pos = text_pos; + + return RE_ERROR_SUCCESS; +} + +/* Checks whether there's a certain string at a position, ignoring case, + * backwards. + */ +Py_LOCAL_INLINE(int) try_match_STRING_FLD_REV(RE_State* state, RE_NextNode* + next, RE_Node* node, Py_ssize_t text_pos, RE_Position* next_position) { + Py_ssize_t length; + Py_UCS4 (*char_at)(void* text, Py_ssize_t pos); + RE_EncodingTable* encoding; + RE_LocaleInfo* locale_info; + int (*full_case_fold)(RE_LocaleInfo* locale_info, Py_UCS4 ch, Py_UCS4* + folded); + Py_ssize_t s_pos; + RE_CODE* values; + int folded_len; + int f_pos; + Py_ssize_t start_pos; + Py_UCS4 folded[RE_MAX_FOLDED]; + + length = (Py_ssize_t)node->value_count; + char_at = state->char_at; + encoding = state->encoding; + locale_info = state->locale_info; + full_case_fold = encoding->full_case_fold; + + s_pos = 0; + values = node->values; + folded_len = 0; + f_pos = 0; + start_pos = text_pos; + + while (s_pos < length) { + if (f_pos >= folded_len) { + /* Fetch and casefold another character. */ + if (text_pos <= state->slice_start) { + if (state->partial_side == RE_PARTIAL_LEFT) { + if (next->match_step == 0) + next_position->text_pos = start_pos; + else + next_position->text_pos = text_pos; + return RE_ERROR_PARTIAL; + } + + return RE_ERROR_FAILURE; + } + + folded_len = full_case_fold(locale_info, char_at(state->text, + text_pos - 1), folded); + f_pos = 0; + } + + if (!same_char_ign(encoding, locale_info, values[length - s_pos - 1], + folded[folded_len - f_pos - 1])) + return RE_ERROR_FAILURE; + + ++s_pos; + ++f_pos; + + if (f_pos >= folded_len) + --text_pos; + } + + if (f_pos < folded_len) + return RE_ERROR_FAILURE; + + next_position->node = next->match_next; + if (next->match_step == 0) + next_position->text_pos = start_pos; + else + next_position->text_pos = text_pos; + + return RE_ERROR_SUCCESS; +} + +/* Checks whether there's a certain string at a position, ignoring case. */ +Py_LOCAL_INLINE(int) try_match_STRING_IGN(RE_State* state, RE_NextNode* next, + RE_Node* node, Py_ssize_t text_pos, RE_Position* next_position) { + Py_ssize_t length; + Py_UCS4 (*char_at)(void* text, Py_ssize_t pos); + RE_EncodingTable* encoding; + RE_LocaleInfo* locale_info; + RE_CODE* values; + Py_ssize_t s_pos; + + length = (Py_ssize_t)node->value_count; + char_at = state->char_at; + encoding = state->encoding; + locale_info = state->locale_info; + values = node->values; + + for (s_pos = 0; s_pos < length; s_pos++) { + if (text_pos + s_pos >= state->slice_end) { + if (state->partial_side == RE_PARTIAL_RIGHT) { + next_position->text_pos = text_pos; + return RE_ERROR_PARTIAL; + } + + return RE_ERROR_FAILURE; + } + + if (!same_char_ign(encoding, locale_info, char_at(state->text, text_pos + + s_pos), values[s_pos])) + return RE_ERROR_FAILURE; + } + + next_position->node = next->match_next; + next_position->text_pos = text_pos + next->match_step; + + return RE_ERROR_SUCCESS; +} + +/* Checks whether there's a certain string at a position, ignoring case, + * backwards. + */ +Py_LOCAL_INLINE(int) try_match_STRING_IGN_REV(RE_State* state, RE_NextNode* + next, RE_Node* node, Py_ssize_t text_pos, RE_Position* next_position) { + Py_ssize_t length; + Py_UCS4 (*char_at)(void* text, Py_ssize_t pos); + RE_EncodingTable* encoding; + RE_LocaleInfo* locale_info; + RE_CODE* values; + Py_ssize_t s_pos; + + length = (Py_ssize_t)node->value_count; + char_at = state->char_at; + encoding = state->encoding; + locale_info = state->locale_info; + values = node->values; + + for (s_pos = 0; s_pos < length; s_pos++) { + if (text_pos - s_pos <= state->slice_start) { + if (state->partial_side == RE_PARTIAL_LEFT) { + next_position->text_pos = text_pos; + return RE_ERROR_PARTIAL; + } + + return RE_ERROR_FAILURE; + } + + if (!same_char_ign(encoding, locale_info, char_at(state->text, text_pos + - s_pos - 1), values[length - s_pos - 1])) + return RE_ERROR_FAILURE; + } + + next_position->node = next->match_next; + next_position->text_pos = text_pos + next->match_step; + + return RE_ERROR_SUCCESS; +} + +/* Checks whether there's a certain string at a position, backwards. */ +Py_LOCAL_INLINE(int) try_match_STRING_REV(RE_State* state, RE_NextNode* next, + RE_Node* node, Py_ssize_t text_pos, RE_Position* next_position) { + Py_ssize_t length; + Py_UCS4 (*char_at)(void* text, Py_ssize_t pos); + RE_CODE* values; + Py_ssize_t s_pos; + + length = (Py_ssize_t)node->value_count; + char_at = state->char_at; + values = node->values; + + for (s_pos = 0; s_pos < length; s_pos++) { + if (text_pos - s_pos <= state->slice_start) { + if (state->partial_side == RE_PARTIAL_LEFT) { + next_position->text_pos = text_pos; + return RE_ERROR_PARTIAL; + } + + return RE_ERROR_FAILURE; + } + + if (!same_char(char_at(state->text, text_pos - s_pos - 1), + values[length - s_pos - 1])) + return RE_ERROR_FAILURE; + } + + next_position->node = next->match_next; + next_position->text_pos = text_pos + next->match_step; + + return RE_ERROR_SUCCESS; +} + +/* Tries a match at the current text position. + * + * Returns the next node and text position if the match succeeds. + */ +Py_LOCAL_INLINE(int) try_match(RE_State* state, RE_NextNode* next, Py_ssize_t + text_pos, RE_Position* next_position) { + RE_Node* test; + int status; + + test = next->test; + + if (test->status & RE_STATUS_FUZZY) { + next_position->node = next->node; + next_position->text_pos = text_pos; + return RE_ERROR_SUCCESS; + } + + switch (test->op) { + case RE_OP_ANY: + status = try_match_ANY(state, test, text_pos); + break; + case RE_OP_ANY_ALL: + status = try_match_ANY_ALL(state, test, text_pos); + break; + case RE_OP_ANY_ALL_REV: + status = try_match_ANY_ALL_REV(state, test, text_pos); + break; + case RE_OP_ANY_REV: + status = try_match_ANY_REV(state, test, text_pos); + break; + case RE_OP_ANY_U: + status = try_match_ANY_U(state, test, text_pos); + break; + case RE_OP_ANY_U_REV: + status = try_match_ANY_U_REV(state, test, text_pos); + break; + case RE_OP_BOUNDARY: + status = try_match_BOUNDARY(state, test, text_pos); + break; + case RE_OP_CHARACTER: + status = try_match_CHARACTER(state, test, text_pos); + break; + case RE_OP_CHARACTER_IGN: + status = try_match_CHARACTER_IGN(state, test, text_pos); + break; + case RE_OP_CHARACTER_IGN_REV: + status = try_match_CHARACTER_IGN_REV(state, test, text_pos); + break; + case RE_OP_CHARACTER_REV: + status = try_match_CHARACTER_REV(state, test, text_pos); + break; + case RE_OP_DEFAULT_BOUNDARY: + status = try_match_DEFAULT_BOUNDARY(state, test, text_pos); + break; + case RE_OP_DEFAULT_END_OF_WORD: + status = try_match_DEFAULT_END_OF_WORD(state, test, text_pos); + break; + case RE_OP_DEFAULT_START_OF_WORD: + status = try_match_DEFAULT_START_OF_WORD(state, test, text_pos); + break; + case RE_OP_END_OF_LINE: + status = try_match_END_OF_LINE(state, test, text_pos); + break; + case RE_OP_END_OF_LINE_U: + status = try_match_END_OF_LINE_U(state, test, text_pos); + break; + case RE_OP_END_OF_STRING: + status = try_match_END_OF_STRING(state, test, text_pos); + break; + case RE_OP_END_OF_STRING_LINE: + status = try_match_END_OF_STRING_LINE(state, test, text_pos); + break; + case RE_OP_END_OF_STRING_LINE_U: + status = try_match_END_OF_STRING_LINE_U(state, test, text_pos); + break; + case RE_OP_END_OF_WORD: + status = try_match_END_OF_WORD(state, test, text_pos); + break; + case RE_OP_GRAPHEME_BOUNDARY: + status = try_match_GRAPHEME_BOUNDARY(state, test, text_pos); + break; + case RE_OP_PROPERTY: + status = try_match_PROPERTY(state, test, text_pos); + break; + case RE_OP_PROPERTY_IGN: + status = try_match_PROPERTY_IGN(state, test, text_pos); + break; + case RE_OP_PROPERTY_IGN_REV: + status = try_match_PROPERTY_IGN_REV(state, test, text_pos); + break; + case RE_OP_PROPERTY_REV: + status = try_match_PROPERTY_REV(state, test, text_pos); + break; + case RE_OP_RANGE: + status = try_match_RANGE(state, test, text_pos); + break; + case RE_OP_RANGE_IGN: + status = try_match_RANGE_IGN(state, test, text_pos); + break; + case RE_OP_RANGE_IGN_REV: + status = try_match_RANGE_IGN_REV(state, test, text_pos); + break; + case RE_OP_RANGE_REV: + status = try_match_RANGE_REV(state, test, text_pos); + break; + case RE_OP_SEARCH_ANCHOR: + status = try_match_SEARCH_ANCHOR(state, test, text_pos); + break; + case RE_OP_SET_DIFF: + case RE_OP_SET_INTER: + case RE_OP_SET_SYM_DIFF: + case RE_OP_SET_UNION: + status = try_match_SET(state, test, text_pos); + break; + case RE_OP_SET_DIFF_IGN: + case RE_OP_SET_INTER_IGN: + case RE_OP_SET_SYM_DIFF_IGN: + case RE_OP_SET_UNION_IGN: + status = try_match_SET_IGN(state, test, text_pos); + break; + case RE_OP_SET_DIFF_IGN_REV: + case RE_OP_SET_INTER_IGN_REV: + case RE_OP_SET_SYM_DIFF_IGN_REV: + case RE_OP_SET_UNION_IGN_REV: + status = try_match_SET_IGN_REV(state, test, text_pos); + break; + case RE_OP_SET_DIFF_REV: + case RE_OP_SET_INTER_REV: + case RE_OP_SET_SYM_DIFF_REV: + case RE_OP_SET_UNION_REV: + status = try_match_SET_REV(state, test, text_pos); + break; + case RE_OP_START_OF_LINE: + status = try_match_START_OF_LINE(state, test, text_pos); + break; + case RE_OP_START_OF_LINE_U: + status = try_match_START_OF_LINE_U(state, test, text_pos); + break; + case RE_OP_START_OF_STRING: + status = try_match_START_OF_STRING(state, test, text_pos); + break; + case RE_OP_START_OF_WORD: + status = try_match_START_OF_WORD(state, test, text_pos); + break; + case RE_OP_STRING: + return try_match_STRING(state, next, test, text_pos, next_position); + case RE_OP_STRING_FLD: + return try_match_STRING_FLD(state, next, test, text_pos, + next_position); + case RE_OP_STRING_FLD_REV: + return try_match_STRING_FLD_REV(state, next, test, text_pos, + next_position); + case RE_OP_STRING_IGN: + return try_match_STRING_IGN(state, next, test, text_pos, + next_position); + case RE_OP_STRING_IGN_REV: + return try_match_STRING_IGN_REV(state, next, test, text_pos, + next_position); + case RE_OP_STRING_REV: + return try_match_STRING_REV(state, next, test, text_pos, + next_position); + case RE_OP_SUCCESS: + if (state->match_all) { + /* We want to match all of the slice. */ + if (state->reverse) { + if (text_pos > state->text_start) + return RE_ERROR_FAILURE; + } else { + if (text_pos < state->text_end) + return RE_ERROR_FAILURE; + } + } + + next_position->node = next->node; + next_position->text_pos = text_pos; + return RE_ERROR_SUCCESS; + default: + next_position->node = next->node; + next_position->text_pos = text_pos; + return RE_ERROR_SUCCESS; + } + + if (status != RE_ERROR_SUCCESS) + return status; + + next_position->node = next->match_next; + next_position->text_pos = text_pos + next->match_step; + + return RE_ERROR_SUCCESS; +} + +/* Searches for a word boundary. */ +Py_LOCAL_INLINE(Py_ssize_t) search_start_BOUNDARY(RE_State* state, RE_Node* + node, Py_ssize_t text_pos, BOOL* is_partial) { + BOOL (*at_boundary)(RE_State* state, Py_ssize_t text_pos); + + at_boundary = state->encoding->at_boundary; + + *is_partial = FALSE; + + for (;;) { + if (at_boundary(state, text_pos) == node->match) + return text_pos; + + if (text_pos >= state->slice_end) + return -1; + + ++text_pos; + } +} + +/* Searches for a word boundary, backwards. */ +Py_LOCAL_INLINE(Py_ssize_t) search_start_BOUNDARY_rev(RE_State* state, RE_Node* + node, Py_ssize_t text_pos, BOOL* is_partial) { + BOOL (*at_boundary)(RE_State* state, Py_ssize_t text_pos); + + at_boundary = state->encoding->at_boundary; + + *is_partial = FALSE; + + for (;;) { + if (at_boundary(state, text_pos) == node->match) + return text_pos; + + if (text_pos <= state->slice_start) + return -1; + + --text_pos; + } +} + +/* Searches for a default word boundary. */ +Py_LOCAL_INLINE(Py_ssize_t) search_start_DEFAULT_BOUNDARY(RE_State* state, + RE_Node* node, Py_ssize_t text_pos, BOOL* is_partial) { + BOOL (*at_default_boundary)(RE_State* state, Py_ssize_t text_pos); + + at_default_boundary = state->encoding->at_default_boundary; + + *is_partial = FALSE; + + for (;;) { + if (at_default_boundary(state, text_pos) == node->match) + return text_pos; + + if (text_pos >= state->slice_end) + return -1; + + ++text_pos; + } +} + +/* Searches for a default word boundary, backwards. */ +Py_LOCAL_INLINE(Py_ssize_t) search_start_DEFAULT_BOUNDARY_rev(RE_State* state, + RE_Node* node, Py_ssize_t text_pos, BOOL* is_partial) { + BOOL (*at_default_boundary)(RE_State* state, Py_ssize_t text_pos); + + at_default_boundary = state->encoding->at_default_boundary; + + *is_partial = FALSE; + + for (;;) { + if (at_default_boundary(state, text_pos) == node->match) + return text_pos; + + if (text_pos <= state->slice_start) + return -1; + + --text_pos; + } +} + +/* Searches for the default end of a word. */ +Py_LOCAL_INLINE(Py_ssize_t) search_start_DEFAULT_END_OF_WORD(RE_State* state, + RE_Node* node, Py_ssize_t text_pos, BOOL* is_partial) { + BOOL (*at_default_word_end)(RE_State* state, Py_ssize_t text_pos); + + at_default_word_end = state->encoding->at_default_word_end; + + *is_partial = FALSE; + + for (;;) { + if (at_default_word_end(state, text_pos) == node->match) + return text_pos; + + if (text_pos >= state->slice_end) + return -1; + + ++text_pos; + } +} + +/* Searches for the default end of a word, backwards. */ +Py_LOCAL_INLINE(Py_ssize_t) search_start_DEFAULT_END_OF_WORD_rev(RE_State* + state, RE_Node* node, Py_ssize_t text_pos, BOOL* is_partial) { + BOOL (*at_default_word_end)(RE_State* state, Py_ssize_t text_pos); + + at_default_word_end = state->encoding->at_default_word_end; + + *is_partial = FALSE; + + for (;;) { + if (at_default_word_end(state, text_pos) == node->match) + return text_pos; + + if (text_pos <= state->slice_start) + return -1; + + --text_pos; + } +} + +/* Searches for the default start of a word. */ +Py_LOCAL_INLINE(Py_ssize_t) search_start_DEFAULT_START_OF_WORD(RE_State* state, + RE_Node* node, Py_ssize_t text_pos, BOOL* is_partial) { + BOOL (*at_default_word_start)(RE_State* state, Py_ssize_t text_pos); + + at_default_word_start = state->encoding->at_default_word_start; + + *is_partial = FALSE; + + for (;;) { + if (at_default_word_start(state, text_pos) == node->match) + return text_pos; + + if (text_pos >= state->slice_end) + return -1; + + ++text_pos; + } +} + +/* Searches for the default start of a word, backwards. */ +Py_LOCAL_INLINE(Py_ssize_t) search_start_DEFAULT_START_OF_WORD_rev(RE_State* + state, RE_Node* node, Py_ssize_t text_pos, BOOL* is_partial) { + BOOL (*at_default_word_start)(RE_State* state, Py_ssize_t text_pos); + + at_default_word_start = state->encoding->at_default_word_start; + + *is_partial = FALSE; + + for (;;) { + if (at_default_word_start(state, text_pos) == node->match) + return text_pos; + + if (text_pos <= state->slice_start) + return -1; + + --text_pos; + } +} + +/* Searches for the end of line. */ +Py_LOCAL_INLINE(Py_ssize_t) search_start_END_OF_LINE(RE_State* state, RE_Node* + node, Py_ssize_t text_pos, BOOL* is_partial) { + *is_partial = FALSE; + + for (;;) { + if (text_pos >= state->text_end || state->char_at(state->text, + text_pos) == '\n') + return text_pos; + + if (text_pos >= state->slice_end) + return -1; + + ++text_pos; + } +} + +/* Searches for the end of line, backwards. */ +Py_LOCAL_INLINE(Py_ssize_t) search_start_END_OF_LINE_rev(RE_State* state, + RE_Node* node, Py_ssize_t text_pos, BOOL* is_partial) { + *is_partial = FALSE; + + for (;;) { + if (text_pos >= state->text_end || state->char_at(state->text, + text_pos) == '\n') + return text_pos; + + if (text_pos <= state->slice_start) + return -1; + + --text_pos; + } +} + +/* Searches for the end of the string. */ +Py_LOCAL_INLINE(Py_ssize_t) search_start_END_OF_STRING(RE_State* state, + RE_Node* node, Py_ssize_t text_pos, BOOL* is_partial) { + *is_partial = FALSE; + + if (state->slice_end >= state->text_end) + return state->text_end; + + return -1; +} + +/* Searches for the end of the string, backwards. */ +Py_LOCAL_INLINE(Py_ssize_t) search_start_END_OF_STRING_rev(RE_State* state, + RE_Node* node, Py_ssize_t text_pos, BOOL* is_partial) { + *is_partial = FALSE; + + if (text_pos >= state->text_end) + return text_pos; + + return -1; +} + +/* Searches for the end of the string or line. */ +Py_LOCAL_INLINE(Py_ssize_t) search_start_END_OF_STRING_LINE(RE_State* state, + RE_Node* node, Py_ssize_t text_pos, BOOL* is_partial) { + *is_partial = FALSE; + + if (text_pos <= state->final_newline) + text_pos = state->final_newline; + else if (text_pos <= state->text_end) + text_pos = state->text_end; + + if (text_pos > state->slice_end) + return -1; + + if (text_pos >= state->text_end) + return text_pos; + + return text_pos; +} + +/* Searches for the end of the string or line, backwards. */ +Py_LOCAL_INLINE(Py_ssize_t) search_start_END_OF_STRING_LINE_rev(RE_State* + state, RE_Node* node, Py_ssize_t text_pos, BOOL* is_partial) { + *is_partial = FALSE; + + if (text_pos >= state->text_end) + text_pos = state->text_end; + else if (text_pos >= state->final_newline) + text_pos = state->final_newline; + else + return -1; + + if (text_pos < state->slice_start) + return -1; + + if (text_pos <= state->text_start) + return text_pos; + + return text_pos; +} + +/* Searches for the end of a word. */ +Py_LOCAL_INLINE(Py_ssize_t) search_start_END_OF_WORD(RE_State* state, RE_Node* + node, Py_ssize_t text_pos, BOOL* is_partial) { + BOOL (*at_word_end)(RE_State* state, Py_ssize_t text_pos); + + at_word_end = state->encoding->at_word_end; + + *is_partial = FALSE; + + for (;;) { + if (at_word_end(state, text_pos) == node->match) + return text_pos; + + if (text_pos >= state->slice_end) + return -1; + + ++text_pos; + } +} + +/* Searches for the end of a word, backwards. */ +Py_LOCAL_INLINE(Py_ssize_t) search_start_END_OF_WORD_rev(RE_State* state, + RE_Node* node, Py_ssize_t text_pos, BOOL* is_partial) { + BOOL (*at_word_end)(RE_State* state, Py_ssize_t text_pos); + + at_word_end = state->encoding->at_word_end; + + *is_partial = FALSE; + + for (;;) { + if (at_word_end(state, text_pos) == node->match) + return text_pos; + + if (text_pos <= state->slice_start) + return -1; + + --text_pos; + } +} + +/* Searches for a grapheme boundary. */ +Py_LOCAL_INLINE(Py_ssize_t) search_start_GRAPHEME_BOUNDARY(RE_State* state, + RE_Node* node, Py_ssize_t text_pos, BOOL* is_partial) { + BOOL (*at_grapheme_boundary)(RE_State* state, Py_ssize_t text_pos); + + at_grapheme_boundary = state->encoding->at_grapheme_boundary; + + *is_partial = FALSE; + + for (;;) { + if (at_grapheme_boundary(state, text_pos) == node->match) + return text_pos; + + if (text_pos >= state->slice_end) + return -1; + + ++text_pos; + } +} + +/* Searches for a grapheme boundary, backwards. */ +Py_LOCAL_INLINE(Py_ssize_t) search_start_GRAPHEME_BOUNDARY_rev(RE_State* state, + RE_Node* node, Py_ssize_t text_pos, BOOL* is_partial) { + BOOL (*at_grapheme_boundary)(RE_State* state, Py_ssize_t text_pos); + + at_grapheme_boundary = state->encoding->at_grapheme_boundary; + + *is_partial = FALSE; + + for (;;) { + if (at_grapheme_boundary(state, text_pos) == node->match) + return text_pos; + + if (text_pos <= state->slice_start) + return -1; + + --text_pos; + } +} + +/* Searches for the start of line. */ +Py_LOCAL_INLINE(Py_ssize_t) search_start_START_OF_LINE(RE_State* state, + RE_Node* node, Py_ssize_t text_pos, BOOL* is_partial) { + *is_partial = FALSE; + + for (;;) { + if (text_pos <= state->text_start || state->char_at(state->text, text_pos - 1) == '\n') + return text_pos; + + if (text_pos >= state->slice_end) + return -1; + + ++text_pos; + } +} + +/* Searches for the start of line, backwards. */ +Py_LOCAL_INLINE(Py_ssize_t) search_start_START_OF_LINE_rev(RE_State* state, + RE_Node* node, Py_ssize_t text_pos, BOOL* is_partial) { + *is_partial = FALSE; + + for (;;) { + if (text_pos <= state->text_start || state->char_at(state->text, text_pos - 1) == '\n') + return text_pos; + + if (text_pos <= state->slice_start) + return -1; + + --text_pos; + } +} + +/* Searches for the start of the string. */ +Py_LOCAL_INLINE(Py_ssize_t) search_start_START_OF_STRING(RE_State* state, + RE_Node* node, Py_ssize_t text_pos, BOOL* is_partial) { + *is_partial = FALSE; + + if (text_pos <= state->text_start) + return text_pos; + + return -1; +} + +/* Searches for the start of the string, backwards. */ +Py_LOCAL_INLINE(Py_ssize_t) search_start_START_OF_STRING_rev(RE_State* state, + RE_Node* node, Py_ssize_t text_pos, BOOL* is_partial) { + *is_partial = FALSE; + + if (state->slice_start <= state->text_start) + return state->text_start; + + return -1; +} + +/* Searches for the start of a word. */ +Py_LOCAL_INLINE(Py_ssize_t) search_start_START_OF_WORD(RE_State* state, + RE_Node* node, Py_ssize_t text_pos, BOOL* is_partial) { + BOOL (*at_word_start)(RE_State* state, Py_ssize_t text_pos); + + at_word_start = state->encoding->at_word_start; + + *is_partial = FALSE; + + for (;;) { + if (at_word_start(state, text_pos) == node->match) + return text_pos; + + if (text_pos >= state->slice_end) + return -1; + + ++text_pos; + } +} + +/* Searches for the start of a word, backwards. */ +Py_LOCAL_INLINE(Py_ssize_t) search_start_START_OF_WORD_rev(RE_State* state, + RE_Node* node, Py_ssize_t text_pos, BOOL* is_partial) { + BOOL (*at_word_start)(RE_State* state, Py_ssize_t text_pos); + + at_word_start = state->encoding->at_word_start; + + *is_partial = FALSE; + + for (;;) { + if (at_word_start(state, text_pos) == node->match) + return text_pos; + + if (text_pos <= state->slice_start) + return -1; + + --text_pos; + } +} + +/* Searches for a string. */ +Py_LOCAL_INLINE(Py_ssize_t) search_start_STRING(RE_State* state, RE_Node* node, + Py_ssize_t text_pos, BOOL* is_partial) { + *is_partial = FALSE; + + if ((node->status & RE_STATUS_REQUIRED) && text_pos == state->req_pos) + return text_pos; + + return string_search(state, node, text_pos, state->slice_end, TRUE, + is_partial); +} + +/* Searches for a string, ignoring case. */ +Py_LOCAL_INLINE(Py_ssize_t) search_start_STRING_FLD(RE_State* state, RE_Node* + node, Py_ssize_t text_pos, Py_ssize_t* new_pos, BOOL* is_partial) { + *is_partial = FALSE; + + if ((node->status & RE_STATUS_REQUIRED) && text_pos == state->req_pos) { + *new_pos = state->req_end; + return text_pos; + } + + return string_search_fld(state, node, text_pos, state->slice_end, new_pos, + is_partial); +} + +/* Searches for a string, ignoring case, backwards. */ +Py_LOCAL_INLINE(Py_ssize_t) search_start_STRING_FLD_REV(RE_State* state, + RE_Node* node, Py_ssize_t text_pos, Py_ssize_t* new_pos, BOOL* is_partial) { + *is_partial = FALSE; + + if ((node->status & RE_STATUS_REQUIRED) && text_pos == state->req_pos) { + *new_pos = state->req_end; + return text_pos; + } + + return string_search_fld_rev(state, node, text_pos, state->slice_start, + new_pos, is_partial); +} + +/* Searches for a string, ignoring case. */ +Py_LOCAL_INLINE(Py_ssize_t) search_start_STRING_IGN(RE_State* state, RE_Node* + node, Py_ssize_t text_pos, BOOL* is_partial) { + *is_partial = FALSE; + + if ((node->status & RE_STATUS_REQUIRED) && text_pos == state->req_pos) + return text_pos; + + return string_search_ign(state, node, text_pos, state->slice_end, TRUE, + is_partial); +} + +/* Searches for a string, ignoring case, backwards. */ +Py_LOCAL_INLINE(Py_ssize_t) search_start_STRING_IGN_REV(RE_State* state, + RE_Node* node, Py_ssize_t text_pos, BOOL* is_partial) { + *is_partial = FALSE; + + if ((node->status & RE_STATUS_REQUIRED) && text_pos == state->req_pos) + return text_pos; + + return string_search_ign_rev(state, node, text_pos, state->slice_start, + TRUE, is_partial); +} + +/* Searches for a string, backwards. */ +Py_LOCAL_INLINE(Py_ssize_t) search_start_STRING_REV(RE_State* state, RE_Node* + node, Py_ssize_t text_pos, BOOL* is_partial) { + *is_partial = FALSE; + + if ((node->status & RE_STATUS_REQUIRED) && text_pos == state->req_pos) + return text_pos; + + return string_search_rev(state, node, text_pos, state->slice_start, TRUE, + is_partial); +} + +/* Searches for the start of a match. */ +Py_LOCAL_INLINE(int) search_start(RE_State* state, RE_NextNode* next, + RE_Position* new_position, int search_index) { + Py_ssize_t start_pos; + RE_Node* test; + RE_Node* node; + RE_SearchPosition* info; + Py_ssize_t text_pos; + + start_pos = state->text_pos; + TRACE(("<> at %" PY_FORMAT_SIZE_T "d\n", start_pos)) + + test = next->test; + node = next->node; + + if (state->reverse) { + if (start_pos < state->slice_start) { + if (state->partial_side == RE_PARTIAL_LEFT) { + new_position->text_pos = state->slice_start; + return RE_ERROR_PARTIAL; + } + + return RE_ERROR_FAILURE; + } + } else { + if (start_pos > state->slice_end) { + if (state->partial_side == RE_PARTIAL_RIGHT) { + new_position->text_pos = state->slice_end; + return RE_ERROR_PARTIAL; + } + } + } + + if (test->status & RE_STATUS_FUZZY) { + /* Don't call 'search_start' again. */ + state->pattern->do_search_start = FALSE; + + state->match_pos = start_pos; + new_position->node = node; + new_position->text_pos = start_pos; + + return RE_ERROR_SUCCESS; + } + +again: + if (!state->is_fuzzy && state->partial_side == RE_PARTIAL_NONE) { + if (state->reverse) { + if (start_pos - state->min_width < state->slice_start) + return RE_ERROR_FAILURE; + } else { + if (start_pos + state->min_width > state->slice_end) + return RE_ERROR_FAILURE; + } + } + + if (search_index < MAX_SEARCH_POSITIONS) { + info = &state->search_positions[search_index]; + if (state->reverse) { + if (info->start_pos >= 0 && info->start_pos >= start_pos && + start_pos >= info->match_pos) { + state->match_pos = info->match_pos; + + new_position->text_pos = state->match_pos; + new_position->node = node; + + return RE_ERROR_SUCCESS; + } + } else { + if (info->start_pos >= 0 && info->start_pos <= start_pos && + start_pos <= info->match_pos) { + state->match_pos = info->match_pos; + + new_position->text_pos = state->match_pos; + new_position->node = node; + + return RE_ERROR_SUCCESS; + } + } + } else + info = NULL; + + switch (test->op) { + case RE_OP_ANY: + start_pos = match_many_ANY(state, test, start_pos, state->slice_end, + FALSE); + + if (start_pos >= state->text_end) { + if (state->partial_side == RE_PARTIAL_RIGHT) { + new_position->text_pos = start_pos; + return RE_ERROR_PARTIAL; + } + } + + if (start_pos >= state->slice_end) + return RE_ERROR_FAILURE; + break; + case RE_OP_ANY_ALL: + case RE_OP_ANY_ALL_REV: + break; + case RE_OP_ANY_REV: + start_pos = match_many_ANY_REV(state, test, start_pos, + state->slice_start, FALSE); + + if (start_pos <= state->text_start) { + if (state->partial_side == RE_PARTIAL_LEFT) { + new_position->text_pos = start_pos; + return RE_ERROR_PARTIAL; + } + } + + if (start_pos <= state->slice_start) + return RE_ERROR_FAILURE; + break; + case RE_OP_ANY_U: + start_pos = match_many_ANY_U(state, test, start_pos, state->slice_end, + FALSE); + + if (start_pos >= state->text_end) { + if (state->partial_side == RE_PARTIAL_RIGHT) { + new_position->text_pos = start_pos; + return RE_ERROR_PARTIAL; + } + } + + if (start_pos >= state->slice_end) + return RE_ERROR_FAILURE; + break; + case RE_OP_ANY_U_REV: + start_pos = match_many_ANY_U_REV(state, test, start_pos, + state->slice_start, FALSE); + + if (start_pos <= state->text_start) { + if (state->partial_side == RE_PARTIAL_LEFT) { + new_position->text_pos = start_pos; + return RE_ERROR_PARTIAL; + } + } + + if (start_pos <= state->slice_start) + return RE_ERROR_FAILURE; + break; + case RE_OP_BOUNDARY: + { + BOOL is_partial; + + if (state->reverse) + start_pos = search_start_BOUNDARY_rev(state, test, start_pos, + &is_partial); + else + start_pos = search_start_BOUNDARY(state, test, start_pos, + &is_partial); + + if (start_pos < 0) + return RE_ERROR_FAILURE; + + if (is_partial) { + new_position->text_pos = start_pos; + return RE_ERROR_PARTIAL; + } + break; + } + case RE_OP_CHARACTER: + start_pos = match_many_CHARACTER(state, test, start_pos, + state->slice_end, FALSE); + + if (start_pos >= state->text_end) { + if (state->partial_side == RE_PARTIAL_RIGHT) { + new_position->text_pos = start_pos; + return RE_ERROR_PARTIAL; + } + } + + if (start_pos >= state->slice_end) + return RE_ERROR_FAILURE; + break; + case RE_OP_CHARACTER_IGN: + start_pos = match_many_CHARACTER_IGN(state, test, start_pos, + state->slice_end, FALSE); + + if (start_pos >= state->text_end) { + if (state->partial_side == RE_PARTIAL_RIGHT) { + new_position->text_pos = start_pos; + return RE_ERROR_PARTIAL; + } + } + + if (start_pos >= state->slice_end) + return RE_ERROR_FAILURE; + break; + case RE_OP_CHARACTER_IGN_REV: + start_pos = match_many_CHARACTER_IGN_REV(state, test, start_pos, + state->slice_start, FALSE); + + if (start_pos <= state->text_start) { + if (state->partial_side == RE_PARTIAL_LEFT) { + new_position->text_pos = start_pos; + return RE_ERROR_PARTIAL; + } + } + + if (start_pos <= state->slice_start) + return RE_ERROR_FAILURE; + break; + case RE_OP_CHARACTER_REV: + start_pos = match_many_CHARACTER_REV(state, test, start_pos, + state->slice_start, FALSE); + + if (start_pos <= state->text_start) { + if (state->partial_side == RE_PARTIAL_LEFT) { + new_position->text_pos = start_pos; + return RE_ERROR_PARTIAL; + } + } + + if (start_pos <= state->slice_start) + return RE_ERROR_FAILURE; + break; + case RE_OP_DEFAULT_BOUNDARY: + { + BOOL is_partial; + + if (state->reverse) + start_pos = search_start_DEFAULT_BOUNDARY_rev(state, test, + start_pos, &is_partial); + else + start_pos = search_start_DEFAULT_BOUNDARY(state, test, start_pos, + &is_partial); + + if (start_pos < 0) + return RE_ERROR_FAILURE; + + if (is_partial) { + new_position->text_pos = start_pos; + return RE_ERROR_PARTIAL; + } + break; + } + case RE_OP_DEFAULT_END_OF_WORD: + { + BOOL is_partial; + + if (state->reverse) + start_pos = search_start_DEFAULT_END_OF_WORD_rev(state, test, + start_pos, &is_partial); + else + start_pos = search_start_DEFAULT_END_OF_WORD(state, test, + start_pos, &is_partial); + + if (start_pos < 0) + return RE_ERROR_FAILURE; + + if (is_partial) { + new_position->text_pos = start_pos; + return RE_ERROR_PARTIAL; + } + break; + } + case RE_OP_DEFAULT_START_OF_WORD: + { + BOOL is_partial; + + if (state->reverse) + start_pos = search_start_DEFAULT_START_OF_WORD_rev(state, test, + start_pos, &is_partial); + else + start_pos = search_start_DEFAULT_START_OF_WORD(state, test, + start_pos, &is_partial); + + if (start_pos < 0) + return RE_ERROR_FAILURE; + + if (is_partial) { + new_position->text_pos = start_pos; + return RE_ERROR_PARTIAL; + } + break; + } + case RE_OP_END_OF_LINE: + { + BOOL is_partial; + + if (state->reverse) + start_pos = search_start_END_OF_LINE_rev(state, test, start_pos, + &is_partial); + else + start_pos = search_start_END_OF_LINE(state, test, start_pos, + &is_partial); + + if (start_pos < 0) + return RE_ERROR_FAILURE; + + if (is_partial) { + new_position->text_pos = start_pos; + return RE_ERROR_PARTIAL; + } + break; + } + case RE_OP_END_OF_STRING: + { + BOOL is_partial; + + if (state->reverse) + start_pos = search_start_END_OF_STRING_rev(state, test, start_pos, + &is_partial); + else + start_pos = search_start_END_OF_STRING(state, test, start_pos, + &is_partial); + + if (start_pos < 0) + return RE_ERROR_FAILURE; + + if (is_partial) { + new_position->text_pos = start_pos; + return RE_ERROR_PARTIAL; + } + break; + } + case RE_OP_END_OF_STRING_LINE: + { + BOOL is_partial; + + if (state->reverse) + start_pos = search_start_END_OF_STRING_LINE_rev(state, test, + start_pos, &is_partial); + else + start_pos = search_start_END_OF_STRING_LINE(state, test, start_pos, + &is_partial); + + if (start_pos < 0) + return RE_ERROR_FAILURE; + + if (is_partial) { + new_position->text_pos = start_pos; + return RE_ERROR_PARTIAL; + } + break; + } + case RE_OP_END_OF_WORD: + { + BOOL is_partial; + + if (state->reverse) + start_pos = search_start_END_OF_WORD_rev(state, test, start_pos, + &is_partial); + else + start_pos = search_start_END_OF_WORD(state, test, start_pos, + &is_partial); + + if (start_pos < 0) + return RE_ERROR_FAILURE; + + if (is_partial) { + new_position->text_pos = start_pos; + return RE_ERROR_PARTIAL; + } + break; + } + case RE_OP_GRAPHEME_BOUNDARY: + { + BOOL is_partial; + + if (state->reverse) + start_pos = search_start_GRAPHEME_BOUNDARY_rev(state, test, + start_pos, &is_partial); + else + start_pos = search_start_GRAPHEME_BOUNDARY(state, test, start_pos, + &is_partial); + + if (start_pos < 0) + return RE_ERROR_FAILURE; + + if (is_partial) { + new_position->text_pos = start_pos; + return RE_ERROR_PARTIAL; + } + break; + } + case RE_OP_PROPERTY: + start_pos = match_many_PROPERTY(state, test, start_pos, + state->slice_end, FALSE); + + if (start_pos >= state->text_end) { + if (state->partial_side == RE_PARTIAL_RIGHT) { + new_position->text_pos = start_pos; + return RE_ERROR_PARTIAL; + } + } + + if (start_pos >= state->slice_end) + return RE_ERROR_FAILURE; + break; + case RE_OP_PROPERTY_IGN: + start_pos = match_many_PROPERTY_IGN(state, test, start_pos, + state->slice_end, FALSE); + + if (start_pos >= state->text_end) { + if (state->partial_side == RE_PARTIAL_RIGHT) { + new_position->text_pos = start_pos; + return RE_ERROR_PARTIAL; + } + } + + if (start_pos >= state->slice_end) + return RE_ERROR_FAILURE; + break; + case RE_OP_PROPERTY_IGN_REV: + start_pos = match_many_PROPERTY_IGN_REV(state, test, start_pos, + state->slice_start, FALSE); + + if (start_pos <= state->text_start) { + if (state->partial_side == RE_PARTIAL_LEFT) { + new_position->text_pos = start_pos; + return RE_ERROR_PARTIAL; + } + } + + if (start_pos <= state->slice_start) + return RE_ERROR_FAILURE; + break; + case RE_OP_PROPERTY_REV: + start_pos = match_many_PROPERTY_REV(state, test, start_pos, + state->slice_start, FALSE); + + if (start_pos <= state->text_start) { + if (state->partial_side == RE_PARTIAL_LEFT) { + new_position->text_pos = start_pos; + return RE_ERROR_PARTIAL; + } + } + + if (start_pos <= state->slice_start) + return RE_ERROR_FAILURE; + break; + case RE_OP_RANGE: + start_pos = match_many_RANGE(state, test, start_pos, state->slice_end, + FALSE); + + if (start_pos >= state->text_end) { + if (state->partial_side == RE_PARTIAL_RIGHT) { + new_position->text_pos = start_pos; + return RE_ERROR_PARTIAL; + } + } + + if (start_pos >= state->slice_end) + return RE_ERROR_FAILURE; + break; + case RE_OP_RANGE_IGN: + start_pos = match_many_RANGE_IGN(state, test, start_pos, + state->slice_end, FALSE); + + if (start_pos >= state->text_end) { + if (state->partial_side == RE_PARTIAL_RIGHT) { + new_position->text_pos = start_pos; + return RE_ERROR_PARTIAL; + } + } + + if (start_pos >= state->slice_end) + return RE_ERROR_FAILURE; + break; + case RE_OP_RANGE_IGN_REV: + start_pos = match_many_RANGE_IGN_REV(state, test, start_pos, + state->slice_start, FALSE); + + if (start_pos <= state->text_start) { + if (state->partial_side == RE_PARTIAL_LEFT) { + new_position->text_pos = start_pos; + return RE_ERROR_PARTIAL; + } + } + + if (start_pos <= state->slice_start) + return RE_ERROR_FAILURE; + break; + case RE_OP_RANGE_REV: + start_pos = match_many_RANGE_REV(state, test, start_pos, + state->slice_start, FALSE); + + if (start_pos <= state->text_start) { + if (state->partial_side == RE_PARTIAL_LEFT) { + new_position->text_pos = start_pos; + return RE_ERROR_PARTIAL; + } + } + + if (start_pos <= state->slice_start) + return RE_ERROR_FAILURE; + break; + case RE_OP_SEARCH_ANCHOR: + if (state->reverse) { + if (start_pos < state->search_anchor) + return RE_ERROR_FAILURE; + } else { + if (start_pos > state->search_anchor) + return RE_ERROR_FAILURE; + } + + start_pos = state->search_anchor; + break; + case RE_OP_SET_DIFF: + case RE_OP_SET_INTER: + case RE_OP_SET_SYM_DIFF: + case RE_OP_SET_UNION: + start_pos = match_many_SET(state, test, start_pos, state->slice_end, + FALSE); + + if (start_pos >= state->text_end) { + if (state->partial_side == RE_PARTIAL_RIGHT) { + new_position->text_pos = start_pos; + return RE_ERROR_PARTIAL; + } + } + + if (start_pos >= state->slice_end) + return FALSE; + break; + case RE_OP_SET_DIFF_IGN: + case RE_OP_SET_INTER_IGN: + case RE_OP_SET_SYM_DIFF_IGN: + case RE_OP_SET_UNION_IGN: + start_pos = match_many_SET_IGN(state, test, start_pos, + state->slice_end, FALSE); + + if (start_pos >= state->text_end) { + if (state->partial_side == RE_PARTIAL_RIGHT) { + new_position->text_pos = start_pos; + return RE_ERROR_PARTIAL; + } + } + + if (start_pos >= state->slice_end) + return FALSE; + break; + case RE_OP_SET_DIFF_IGN_REV: + case RE_OP_SET_INTER_IGN_REV: + case RE_OP_SET_SYM_DIFF_IGN_REV: + case RE_OP_SET_UNION_IGN_REV: + start_pos = match_many_SET_IGN_REV(state, test, start_pos, + state->slice_start, FALSE); + + if (start_pos <= state->text_start) { + if (state->partial_side == RE_PARTIAL_LEFT) { + new_position->text_pos = start_pos; + return RE_ERROR_PARTIAL; + } + } + + if (start_pos <= state->slice_start) + return FALSE; + break; + case RE_OP_SET_DIFF_REV: + case RE_OP_SET_INTER_REV: + case RE_OP_SET_SYM_DIFF_REV: + case RE_OP_SET_UNION_REV: + start_pos = match_many_SET_REV(state, test, start_pos, + state->slice_start, FALSE); + + if (start_pos <= state->text_start) { + if (state->partial_side == RE_PARTIAL_LEFT) { + new_position->text_pos = start_pos; + return RE_ERROR_PARTIAL; + } + } + + if (start_pos <= state->slice_start) + return FALSE; + break; + case RE_OP_START_OF_LINE: + { + BOOL is_partial; + + if (state->reverse) + start_pos = search_start_START_OF_LINE_rev(state, test, start_pos, + &is_partial); + else + start_pos = search_start_START_OF_LINE(state, test, start_pos, + &is_partial); + + if (start_pos < 0) + return RE_ERROR_FAILURE; + + if (is_partial) { + new_position->text_pos = start_pos; + return RE_ERROR_PARTIAL; + } + break; + } + case RE_OP_START_OF_STRING: + { + BOOL is_partial; + + if (state->reverse) + start_pos = search_start_START_OF_STRING_rev(state, test, + start_pos, &is_partial); + else + start_pos = search_start_START_OF_STRING(state, test, start_pos, + &is_partial); + + if (start_pos < 0) + return RE_ERROR_FAILURE; + + if (is_partial) { + new_position->text_pos = start_pos; + return RE_ERROR_PARTIAL; + } + break; + } + case RE_OP_START_OF_WORD: + { + BOOL is_partial; + + if (state->reverse) + start_pos = search_start_START_OF_WORD_rev(state, test, start_pos, + &is_partial); + else + start_pos = search_start_START_OF_WORD(state, test, start_pos, + &is_partial); + + if (start_pos < 0) + return RE_ERROR_FAILURE; + + if (is_partial) { + new_position->text_pos = start_pos; + return RE_ERROR_PARTIAL; + } + break; + } + case RE_OP_STRING: + { + BOOL is_partial; + + start_pos = search_start_STRING(state, test, start_pos, &is_partial); + if (start_pos < 0) + return RE_ERROR_FAILURE; + + if (is_partial) { + new_position->text_pos = start_pos; + return RE_ERROR_PARTIAL; + } + break; + } + case RE_OP_STRING_FLD: + { + Py_ssize_t new_pos; + BOOL is_partial; + + start_pos = search_start_STRING_FLD(state, test, start_pos, &new_pos, + &is_partial); + if (start_pos < 0) + return RE_ERROR_FAILURE; + + if (is_partial) { + new_position->text_pos = start_pos; + return RE_ERROR_PARTIAL; + } + + /* Can we look further ahead? */ + if (test == node) { + if (test->next_1.node) { + int status; + + status = try_match(state, &test->next_1, new_pos, + new_position); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) { + ++start_pos; + + if (start_pos >= state->slice_end) { + if (state->partial_side == RE_PARTIAL_RIGHT) { + new_position->text_pos = state->slice_start; + return RE_ERROR_PARTIAL; + } + + return RE_ERROR_FAILURE; + } + + goto again; + } + } + + /* It's a possible match. */ + state->match_pos = start_pos; + + if (info) { + info->start_pos = state->text_pos; + info->match_pos = state->match_pos; + } + + return RE_ERROR_SUCCESS; + } + break; + } + case RE_OP_STRING_FLD_REV: + { + Py_ssize_t new_pos; + BOOL is_partial; + + start_pos = search_start_STRING_FLD_REV(state, test, start_pos, + &new_pos, &is_partial); + if (start_pos < 0) + return RE_ERROR_FAILURE; + + if (is_partial) { + new_position->text_pos = start_pos; + return RE_ERROR_PARTIAL; + } + + /* Can we look further ahead? */ + if (test == node) { + if (test->next_1.node) { + int status; + + status = try_match(state, &test->next_1, new_pos, + new_position); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) { + --start_pos; + + if (start_pos <= state->slice_start) { + if (state->partial_side == RE_PARTIAL_LEFT) { + new_position->text_pos = state->slice_start; + return RE_ERROR_PARTIAL; + } + + return RE_ERROR_FAILURE; + } + + goto again; + } + } + + /* It's a possible match. */ + state->match_pos = start_pos; + + if (info) { + info->start_pos = state->text_pos; + info->match_pos = state->match_pos; + } + + return RE_ERROR_SUCCESS; + } + break; + } + case RE_OP_STRING_IGN: + { + BOOL is_partial; + + start_pos = search_start_STRING_IGN(state, test, start_pos, + &is_partial); + if (start_pos < 0) + return RE_ERROR_FAILURE; + + if (is_partial) { + new_position->text_pos = start_pos; + return RE_ERROR_PARTIAL; + } + break; + } + case RE_OP_STRING_IGN_REV: + { + BOOL is_partial; + + start_pos = search_start_STRING_IGN_REV(state, test, start_pos, + &is_partial); + if (start_pos < 0) + return RE_ERROR_FAILURE; + + if (is_partial) { + new_position->text_pos = start_pos; + return RE_ERROR_PARTIAL; + } + break; + } + case RE_OP_STRING_REV: + { + BOOL is_partial; + + start_pos = search_start_STRING_REV(state, test, start_pos, + &is_partial); + if (start_pos < 0) + return RE_ERROR_FAILURE; + + if (is_partial) { + new_position->text_pos = start_pos; + return RE_ERROR_PARTIAL; + } + break; + } + default: + /* Don't call 'search_start' again. */ + state->pattern->do_search_start = FALSE; + + state->match_pos = start_pos; + new_position->node = node; + new_position->text_pos = start_pos; + return RE_ERROR_SUCCESS; + } + + /* Can we look further ahead? */ + if (test == node) { + text_pos = start_pos + test->step; + + if (test->next_1.node) { + int status; + + status = try_match(state, &test->next_1, text_pos, new_position); + if (status == RE_ERROR_PARTIAL) { + new_position->node = node; + new_position->text_pos = start_pos; + return status; + } + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) { + if (state->reverse) { + --start_pos; + + if (start_pos < state->slice_start) { + if (state->partial_side == RE_PARTIAL_LEFT) { + new_position->text_pos = state->slice_start; + return RE_ERROR_PARTIAL; + } + + return RE_ERROR_FAILURE; + } + } else { + ++start_pos; + + if (start_pos > state->slice_end) { + if (state->partial_side == RE_PARTIAL_RIGHT) { + new_position->text_pos = state->slice_end; + return RE_ERROR_PARTIAL; + } + + return RE_ERROR_FAILURE; + } + } + + goto again; + } + } + } else { + new_position->node = node; + new_position->text_pos = start_pos; + } + + /* It's a possible match. */ + state->match_pos = start_pos; + + if (info) { + info->start_pos = state->text_pos; + info->match_pos = state->match_pos; + } + + return RE_ERROR_SUCCESS; +} + +/* Saves a capture group. */ +Py_LOCAL_INLINE(BOOL) save_capture(RE_State* state, size_t private_index, + size_t public_index, RE_GroupSpan span) { + RE_GroupData* group; + + /* Capture group indexes are 1-based (excluding group 0, which is the + * entire matched string). + */ + group = &state->groups[public_index - 1]; + + if (group->count >= group->capacity) { + size_t new_capacity; + RE_GroupSpan* new_captures; + + new_capacity = group->capacity * 2; + + if (new_capacity == 0) + new_capacity = 16; + + new_captures = (RE_GroupSpan*)safe_realloc(state, group->captures, + new_capacity * sizeof(RE_GroupSpan)); + if (!new_captures) + return FALSE; + + group->captures = new_captures; + group->capacity = new_capacity; + } + + group->captures[group->count++] = span; + + return TRUE; +} + +/* Unsaves a capture group. */ +Py_LOCAL_INLINE(void) unsave_capture(RE_State* state, size_t private_index, + size_t public_index) { + RE_GroupData* group; + + /* Capture group indexes are 1-based (excluding group 0, which is the + * entire matched string). + */ + group = &state->groups[public_index - 1]; + + if (group->count > 0) + --group->count; +} + +/* Inserts a new span in a guard list. */ +Py_LOCAL_INLINE(BOOL) insert_guard_span(RE_State* state, RE_GuardList* + guard_list, size_t index) { + size_t n; + + if (guard_list->count >= guard_list->capacity) { + size_t new_capacity; + RE_GuardSpan* new_spans; + + new_capacity = guard_list->capacity * 2; + + if (new_capacity == 0) + new_capacity = 16; + + new_spans = (RE_GuardSpan*)safe_realloc(state, guard_list->spans, + new_capacity * sizeof(RE_GuardSpan)); + if (!new_spans) + return FALSE; + + guard_list->capacity = new_capacity; + guard_list->spans = new_spans; + } + + n = guard_list->count - index; + if (n > 0) + memmove(guard_list->spans + index + 1, guard_list->spans + index, n * + sizeof(RE_GuardSpan)); + ++guard_list->count; + + return TRUE; +} + +/* Deletes a span in a guard list. */ +Py_LOCAL_INLINE(void) delete_guard_span(RE_GuardList* guard_list, size_t index) + { + size_t n; + + n = guard_list->count - index - 1; + if (n > 0) + memmove(guard_list->spans + index, guard_list->spans + index + 1, n * + sizeof(RE_GuardSpan)); + --guard_list->count; +} + +/* Checks whether a position is guarded against further matching. */ +Py_LOCAL_INLINE(BOOL) is_guarded(RE_GuardList* guard_list, Py_ssize_t text_pos) + { + Py_ssize_t below; + Py_ssize_t above; + RE_GuardSpan* spans; + Py_ssize_t count; + + guard_list->last_text_pos = -1; + + spans = guard_list->spans; + count = (Py_ssize_t)guard_list->count; + + if (count == 0 || text_pos < spans[0].low || text_pos > spans[count - + 1].high) + return FALSE; + + below = -1; + above = count; + + while (above - below > 1) { + Py_ssize_t mid; + RE_GuardSpan* span; + + mid = (below + above) / 2; + span = &spans[mid]; + + if (text_pos < span->low) + above = mid; + else if (text_pos > span->high) + below = mid; + else + return span->protect; + } + + return FALSE; +} + +/* Guards a position against further matching. */ +Py_LOCAL_INLINE(BOOL) guard(RE_State* state, RE_GuardList* guard_list, + Py_ssize_t text_pos, BOOL protect) { + Py_ssize_t below; + Py_ssize_t above; + RE_GuardSpan* spans; + Py_ssize_t count; + + guard_list->last_text_pos = -1; + + spans = guard_list->spans; + count = (Py_ssize_t)guard_list->count; + + if (count > 0 && text_pos > spans[count - 1].high) { + below = count - 1; + above = count; + } else if (count > 0 && text_pos < spans[0].low) { + below = -1; + above = 0; + } else { + below = -1; + above = count; + + while (above - below > 1) { + Py_ssize_t mid; + RE_GuardSpan* span; + + mid = (below + above) / 2; + span = &spans[mid]; + + if (text_pos < span->low) + above = mid; + else if (text_pos > span->high) + below = mid; + else + return TRUE; + } + } + + /* Add the position to the guard list. */ + if (below >= 0 && text_pos - spans[below].high == 1 && spans[below].protect + == protect) { + if (above < count && spans[above].low - text_pos == 1 && + spans[above].protect == protect) { + /* The new position joins 2 spans */ + spans[below].high = spans[above].high; + delete_guard_span(guard_list, (size_t)above); + } else { + /* The new position is just above the 'below' span. */ + spans[below].high = text_pos; + } + } else if (above < count && spans[above].low - text_pos == 1 && + spans[above].protect == protect) { + /* The new position is just below the 'above' span. */ + spans[above].low = text_pos; + } else { + /* Insert a new span. */ + if (!insert_guard_span(state, guard_list, (size_t)above)) + return FALSE; + spans = guard_list->spans; + spans[above].low = text_pos; + spans[above].high = text_pos; + spans[above].protect = protect; + } + + return TRUE; +} + +/* Guards a position against further matching for a repeat. */ +Py_LOCAL_INLINE(BOOL) guard_repeat(RE_State* state, size_t index, Py_ssize_t + text_pos, RE_STATUS_T guard_type, BOOL protect) { + RE_GuardList* guard_list; + + /* Is a guard active here? */ + if (!(state->pattern->repeat_info[index].status & guard_type)) + return TRUE; + + /* Which guard list? */ + if (guard_type & RE_STATUS_BODY) + guard_list = &state->repeats[index].body_guard_list; + else + guard_list = &state->repeats[index].tail_guard_list; + + return guard(state, guard_list, text_pos, protect); +} + +/* Guards a range of positions against further matching. */ +Py_LOCAL_INLINE(Py_ssize_t) guard_range(RE_State* state, RE_GuardList* + guard_list, Py_ssize_t lo_pos, Py_ssize_t hi_pos, BOOL protect) { + Py_ssize_t below; + Py_ssize_t above; + RE_GuardSpan* spans; + Py_ssize_t count; + + guard_list->last_text_pos = -1; + + spans = guard_list->spans; + count = (Py_ssize_t)guard_list->count; + + below = -1; + above = count; + + while (above - below > 1) { + Py_ssize_t mid; + RE_GuardSpan* span; + + mid = (below + above) / 2; + span = &spans[mid]; + + if (lo_pos < span->low) + above = mid; + else if (lo_pos > span->high) + below = mid; + else + return span->high + 1; + } + + /* Add the range to the guard list. */ + if (below >= 0 && lo_pos - spans[below].high == 1 && spans[below].protect + == protect) { + if (above < count && spans[above].low - hi_pos <= 1 && + spans[above].protect == protect) { + /* The new range joins the spans */ + spans[below].high = spans[above].high; + delete_guard_span(guard_list, (size_t)above); + spans = guard_list->spans; + } else { + if (above < count) + hi_pos = min_ssize_t(hi_pos, spans[above].low - 1); + + spans[below].high = hi_pos; + } + + lo_pos = spans[below].high + 1; + } else if (above < count && spans[above].low - hi_pos <= 1 && + spans[above].protect == protect) { + spans[above].low = lo_pos; + lo_pos = spans[above].high + 1; + } else { + /* Insert a new span. */ + if (!insert_guard_span(state, guard_list, (size_t)above)) + return -1; + spans = guard_list->spans; + + if (above < count) + hi_pos = min_ssize_t(hi_pos, spans[above].low - 1); + + spans[above].low = lo_pos; + spans[above].high = hi_pos; + spans[above].protect = protect; + lo_pos = spans[above].high + 1; + } + + return lo_pos; +} + +/* Guards a range of positions against further matching for a repeat. */ +Py_LOCAL_INLINE(BOOL) guard_repeat_range(RE_State* state, size_t index, + Py_ssize_t lo_pos, Py_ssize_t hi_pos, RE_STATUS_T guard_type, BOOL protect) { + RE_GuardList* guard_list; + + /* Is a guard active here? */ + if (!(state->pattern->repeat_info[index].status & guard_type)) + return TRUE; + + /* Which guard list? */ + if (guard_type & RE_STATUS_BODY) + guard_list = &state->repeats[index].body_guard_list; + else + guard_list = &state->repeats[index].tail_guard_list; + + while (lo_pos <= hi_pos) { + lo_pos = guard_range(state, guard_list, lo_pos, hi_pos, protect); + if (lo_pos < 0) + return FALSE; + } + + return TRUE; +} + +/* Checks whether a position is guarded against further matching for a repeat. + */ +Py_LOCAL_INLINE(BOOL) is_repeat_guarded(RE_State* state, size_t index, + Py_ssize_t text_pos, RE_STATUS_T guard_type) { + RE_GuardList* guard_list; + + /* Is a guard active here? */ + if (!(state->pattern->repeat_info[index].status & guard_type) || + state->is_fuzzy) + return FALSE; + + /* Which guard list? */ + if (guard_type == RE_STATUS_BODY) + guard_list = &state->repeats[index].body_guard_list; + else + guard_list = &state->repeats[index].tail_guard_list; + + return is_guarded(guard_list, text_pos); +} + +/* Builds a Unicode string. */ +Py_LOCAL_INLINE(PyObject*) build_unicode_value(void* buffer, Py_ssize_t start, + Py_ssize_t end, Py_ssize_t buffer_charsize) { + Py_ssize_t len; + int kind; + + buffer = (void*)((RE_UINT8*)buffer + start * buffer_charsize); + len = end - start; + + switch (buffer_charsize) { + case 1: + kind = PyUnicode_1BYTE_KIND; + break; + case 2: + kind = PyUnicode_2BYTE_KIND; + break; + case 4: + kind = PyUnicode_4BYTE_KIND; + break; + default: + kind = PyUnicode_1BYTE_KIND; + break; + } + + return PyUnicode_FromKindAndData(kind, buffer, len); +} + +/* Builds a bytestring. Returns NULL if any member is too wide. */ +Py_LOCAL_INLINE(PyObject*) build_bytes_value(void* buffer, Py_ssize_t start, + Py_ssize_t end, Py_ssize_t buffer_charsize) { + Py_ssize_t len; + Py_UCS1* byte_buffer; + Py_ssize_t i; + PyObject* result; + + buffer = (void*)((RE_UINT8*)buffer + start * buffer_charsize); + len = end - start; + + if (buffer_charsize == 1) + return Py_BuildValue("y#", buffer, len); + + byte_buffer = re_alloc((size_t)len); + if (!byte_buffer) + return NULL; + + for (i = 0; i < len; i++) { + Py_UCS2 c = ((Py_UCS2*)buffer)[i]; + if (c > 0xFF) + goto too_wide; + + byte_buffer[i] = (Py_UCS1)c; + } + + result = Py_BuildValue("y#", byte_buffer, len); + + re_dealloc(byte_buffer); + + return result; + +too_wide: + re_dealloc(byte_buffer); + + return NULL; +} + +/* Calculates the total number of errors. */ +Py_LOCAL_INLINE(size_t) total_errors(size_t* fuzzy_counts) { + return fuzzy_counts[RE_FUZZY_DEL] + fuzzy_counts[RE_FUZZY_INS] + + fuzzy_counts[RE_FUZZY_SUB]; +} + +/* Calculates the total cost of the errors. */ +Py_LOCAL_INLINE(size_t) total_cost(size_t* fuzzy_counts, RE_Node* fuzzy_node) { + RE_CODE* values; + + values = fuzzy_node->values; + + return fuzzy_counts[RE_FUZZY_DEL] * values[RE_FUZZY_VAL_DEL_COST] + + fuzzy_counts[RE_FUZZY_INS] * values[RE_FUZZY_VAL_INS_COST] + + fuzzy_counts[RE_FUZZY_SUB] * values[RE_FUZZY_VAL_SUB_COST]; +} + +/* Checks whether any additional fuzzy error is permitted. */ +Py_LOCAL_INLINE(BOOL) any_error_permitted(RE_State* state) { + size_t* fuzzy_counts; + RE_CODE* values; + size_t error_count; + size_t cost; + + fuzzy_counts = state->fuzzy_counts; + values = state->fuzzy_node->values; + error_count = total_errors(fuzzy_counts); + cost = total_cost(fuzzy_counts, state->fuzzy_node); + + return cost <= values[RE_FUZZY_VAL_MAX_COST] && error_count < + state->max_errors; +} + +/* Checks whether this additional fuzzy error is permitted. */ +Py_LOCAL_INLINE(BOOL) this_error_permitted(RE_State* state, RE_UINT8 + fuzzy_type) { + size_t* fuzzy_counts; + RE_CODE* values; + size_t error_count; + size_t cost; + + fuzzy_counts = state->fuzzy_counts; + values = state->fuzzy_node->values; + error_count = total_errors(fuzzy_counts); + cost = total_cost(fuzzy_counts, state->fuzzy_node); + + return fuzzy_counts[fuzzy_type] < values[RE_FUZZY_VAL_MAX_BASE + + fuzzy_type] && error_count < values[RE_FUZZY_VAL_MAX_ERR] && error_count + < state->max_errors && cost + values[RE_FUZZY_VAL_COST_BASE + fuzzy_type] + <= values[RE_FUZZY_VAL_MAX_COST]; +} + +/* Checks whether an insertion is permitted. */ +Py_LOCAL_INLINE(BOOL) insertion_permitted(RE_State* state, RE_Node* fuzzy_node, + size_t* fuzzy_counts) { + RE_CODE* values; + size_t error_count; + size_t cost; + + values = fuzzy_node->values; + error_count = total_errors(fuzzy_counts); + cost = total_cost(fuzzy_counts, fuzzy_node); + + return fuzzy_counts[RE_FUZZY_INS] < values[RE_FUZZY_VAL_MAX_INS] && + error_count < values[RE_FUZZY_VAL_MAX_ERR] && cost + + values[RE_FUZZY_VAL_INS_COST] <= values[RE_FUZZY_VAL_MAX_COST] && + error_count < state->max_errors; +} + +/* Checks whether the errors are within the fuzzy constraints. */ +Py_LOCAL_INLINE(BOOL) fuzzy_within_constraints(size_t* fuzzy_counts, RE_Node* + fuzzy_node, size_t max_errors) { + RE_CODE* values; + size_t del_count; + size_t ins_count; + size_t sub_count; + size_t err_count; + + values = fuzzy_node->values; + del_count = fuzzy_counts[RE_FUZZY_DEL]; + ins_count = fuzzy_counts[RE_FUZZY_INS]; + sub_count = fuzzy_counts[RE_FUZZY_SUB]; + + if (del_count < values[RE_FUZZY_VAL_MIN_DEL] || del_count > + values[RE_FUZZY_VAL_MAX_DEL]) + return FALSE; + if (ins_count < values[RE_FUZZY_VAL_MIN_INS] || ins_count > + values[RE_FUZZY_VAL_MAX_INS]) + return FALSE; + if (sub_count < values[RE_FUZZY_VAL_MIN_SUB] || sub_count > + values[RE_FUZZY_VAL_MAX_SUB]) + return FALSE; + + err_count = del_count + ins_count + sub_count; + + if (err_count < values[RE_FUZZY_VAL_MIN_ERR] || err_count > + values[RE_FUZZY_VAL_MAX_ERR]) + return FALSE; + + if (err_count > max_errors) + return FALSE; + + return total_cost(fuzzy_counts, fuzzy_node) <= + values[RE_FUZZY_VAL_MAX_COST]; +} + +/* Checks whether we've reached the end of the text during a fuzzy partial + * match. + */ +Py_LOCAL_INLINE(int) check_fuzzy_partial(RE_State* state, Py_ssize_t text_pos) + { + switch (state->partial_side) { + case RE_PARTIAL_LEFT: + if (text_pos < state->text_start) + return RE_ERROR_PARTIAL; + break; + case RE_PARTIAL_RIGHT: + if (text_pos > state->text_end) + return RE_ERROR_PARTIAL; + break; + } + + return RE_ERROR_FAILURE; +} + +/* Records a fuzzy change. */ +Py_LOCAL_INLINE(BOOL) record_fuzzy(RE_State* state, RE_UINT8 fuzzy_type, + Py_ssize_t text_pos) { + RE_FuzzyChangesList* change_list; + RE_FuzzyChange* change; + + change_list = &state->fuzzy_changes; + + if (change_list->count >= change_list->capacity) { + size_t new_capacity; + RE_FuzzyChange* new_items; + + new_capacity = change_list->capacity * 2; + + if (new_capacity == 0) + new_capacity = 64; + + new_items = (RE_FuzzyChange*)safe_realloc(state, change_list->items, + new_capacity * sizeof(RE_FuzzyChange)); + if (!new_items) + return FALSE; + + change_list->items = new_items; + change_list->capacity = new_capacity; + } + + change = &change_list->items[change_list->count++]; + change->type = fuzzy_type; + change->pos = text_pos; + + return TRUE; +} + +/* "Unrecords" a change in a fuzzy change. */ +Py_LOCAL_INLINE(void) unrecord_fuzzy(RE_State* state) { + --state->fuzzy_changes.count; +} + +/* Initialises a list of fuzzy changes. */ +Py_LOCAL_INLINE(void) init_fuzzy_changes_list(RE_FuzzyChangesList* + changes_list) { + changes_list->capacity = 0; + changes_list->count = 0; + changes_list->items = NULL; +} + +/* Finalises a list of fuzzy changes. */ +Py_LOCAL_INLINE(void) fini_fuzzy_changes_list(RE_State* state, + RE_FuzzyChangesList* changes_list) { + safe_dealloc(state, changes_list->items); + changes_list->capacity = 0; + changes_list->count = 0; + changes_list->items = NULL; +} + +/* Initialises a list of lists of fuzzy changes. */ +Py_LOCAL_INLINE(void) init_best_changes_list(RE_BestChangesList* + best_changes_list) { + best_changes_list->capacity = 0; + best_changes_list->count = 0; + best_changes_list->lists = NULL; +} + +/* Clears a list of lists of fuzzy changes. */ +Py_LOCAL_INLINE(void) clear_best_fuzzy_changes(RE_State* state, + RE_BestChangesList* best_changes_list) { + size_t i; + + for (i = 0; i < best_changes_list->count; i++) { + RE_FuzzyChangesList* list; + + list = &best_changes_list->lists[i]; + list->capacity = 0; + list->count = 0; + safe_dealloc(state, list->items); + list->items = NULL; + } + + best_changes_list->count = 0; +} + +/* Finalises a list of lists of fuzzy changes. */ +Py_LOCAL_INLINE(void) fini_best_changes_list(RE_State* state, + RE_BestChangesList* best_changes_list) { + clear_best_fuzzy_changes(state, best_changes_list); + safe_dealloc(state, best_changes_list->lists); + best_changes_list->capacity = 0; + best_changes_list->count = 0; + best_changes_list->lists = NULL; +} + +/* Adds a list of fuzzy changes to a list of best fuzzy changes. */ +Py_LOCAL_INLINE(BOOL) add_best_fuzzy_changes(RE_State* state, + RE_BestChangesList* best_changes_list) { + size_t size; + RE_FuzzyChange* items; + RE_FuzzyChangesList* changes; + + if (best_changes_list->count >= best_changes_list->capacity) { + size_t new_capacity; + RE_FuzzyChangesList* new_lists; + + new_capacity = best_changes_list->capacity * 2; + + if (new_capacity == 0) + new_capacity = 64; + + new_lists = (RE_FuzzyChangesList*)safe_realloc(state, + best_changes_list->lists, new_capacity * + sizeof(RE_FuzzyChangesList)); + if (!new_lists) + return FALSE; + + best_changes_list->lists = new_lists; + best_changes_list->capacity = new_capacity; + } + + size = (size_t)state->fuzzy_changes.count * sizeof(RE_FuzzyChange); + items = (RE_FuzzyChange*)safe_alloc(state, size); + if (!items) + return FALSE; + Py_MEMCPY(items, state->fuzzy_changes.items, size); + + changes = &best_changes_list->lists[best_changes_list->count++]; + changes->capacity = state->fuzzy_changes.count; + changes->count = state->fuzzy_changes.count; + changes->items = items; + + return TRUE; +} + +/* Saves a list of fuzzy changes. */ +Py_LOCAL_INLINE(BOOL) save_fuzzy_changes(RE_State* state, RE_FuzzyChangesList* + best_changes_list) { + if (state->fuzzy_changes.count > best_changes_list->capacity) { + size_t new_capacity; + RE_FuzzyChange* new_items; + + new_capacity = best_changes_list->capacity; + + if (new_capacity == 0) + new_capacity = 64; + + while (state->fuzzy_changes.count > new_capacity) + new_capacity *= 2; + + new_items = (RE_FuzzyChange*)safe_realloc(state, + best_changes_list->items, new_capacity * sizeof(RE_FuzzyChange)); + if (!new_items) + return FALSE; + + best_changes_list->items = new_items; + best_changes_list->capacity = new_capacity; + } + + Py_MEMCPY(best_changes_list->items, state->fuzzy_changes.items, + (size_t)state->fuzzy_changes.count * sizeof(RE_FuzzyChange)); + best_changes_list->count = state->fuzzy_changes.count; + + return TRUE; +} + +/* Restores a list of fuzzy changes. */ +Py_LOCAL_INLINE(void) restore_fuzzy_changes(RE_State* state, + RE_FuzzyChangesList* best_changes_list) { + Py_MEMCPY(state->fuzzy_changes.items, best_changes_list->items, + (size_t)best_changes_list->count * sizeof(RE_FuzzyChange)); + state->fuzzy_changes.count = best_changes_list->count; +} + +/* Does the test of a FUZZY_EXT. */ +Py_LOCAL_INLINE(BOOL) fuzzy_ext_match(RE_State* state, RE_Node* fuzzy_node, + Py_ssize_t pos) { + RE_Node* test_node; + + if (!fuzzy_node) + return TRUE; + + test_node = fuzzy_node->nonstring.next_2.node; + if (!test_node) + return TRUE; + + switch (test_node->op) { + case RE_OP_CHARACTER: + return pos < state->slice_end && matches_CHARACTER(state->encoding, + state->locale_info, test_node, state->char_at(state->text, pos)) == + test_node->match; + case RE_OP_CHARACTER_IGN: + return pos < state->slice_end && matches_CHARACTER_IGN(state->encoding, + state->locale_info, test_node, state->char_at(state->text, pos)) == + test_node->match; + case RE_OP_CHARACTER_IGN_REV: + return pos > state->slice_start && + matches_CHARACTER_IGN(state->encoding, state->locale_info, test_node, + state->char_at(state->text, pos - 1)) == test_node->match; + case RE_OP_CHARACTER_REV: + return pos > state->slice_start && matches_CHARACTER(state->encoding, + state->locale_info, test_node, state->char_at(state->text, pos - 1)) + == test_node->match; + case RE_OP_PROPERTY: + return pos < state->slice_end && matches_PROPERTY(state->encoding, + state->locale_info, test_node, state->char_at(state->text, pos)) == + test_node->match; + case RE_OP_PROPERTY_IGN: + return pos < state->slice_end && matches_PROPERTY_IGN(state->encoding, + state->locale_info, test_node, state->char_at(state->text, pos)) == + test_node->match; + case RE_OP_PROPERTY_IGN_REV: + return pos > state->slice_start && + matches_PROPERTY_IGN(state->encoding, state->locale_info, test_node, + state->char_at(state->text, pos - 1)) == test_node->match; + case RE_OP_PROPERTY_REV: + return pos > state->slice_start && matches_PROPERTY(state->encoding, + state->locale_info, test_node, state->char_at(state->text, pos - 1)) + == test_node->match; + case RE_OP_RANGE: + return pos < state->slice_end && matches_RANGE(state->encoding, + state->locale_info, test_node, state->char_at(state->text, pos)) == + test_node->match; + case RE_OP_RANGE_IGN: + return pos < state->slice_end && matches_RANGE_IGN(state->encoding, + state->locale_info, test_node, state->char_at(state->text, pos)) == + test_node->match; + case RE_OP_RANGE_IGN_REV: + return pos > state->slice_start && matches_RANGE_IGN(state->encoding, + state->locale_info, test_node, state->char_at(state->text, pos - 1)) + == test_node->match; + case RE_OP_RANGE_REV: + return pos > state->slice_start && matches_RANGE(state->encoding, + state->locale_info, test_node, state->char_at(state->text, pos - 1)) + == test_node->match; + case RE_OP_SET_DIFF: + case RE_OP_SET_INTER: + case RE_OP_SET_SYM_DIFF: + case RE_OP_SET_UNION: + return pos < state->slice_end && matches_SET(state->encoding, + state->locale_info, test_node, state->char_at(state->text, pos)) == + test_node->match; + case RE_OP_SET_DIFF_IGN: + case RE_OP_SET_INTER_IGN: + case RE_OP_SET_SYM_DIFF_IGN: + case RE_OP_SET_UNION_IGN: + return pos < state->slice_end && matches_SET_IGN(state->encoding, + state->locale_info, test_node, state->char_at(state->text, pos)) == + test_node->match; + } + + return TRUE; +} + +/* Gets the folded character at a certain position. */ +Py_LOCAL_INLINE(Py_UCS4) folded_char_at(RE_State* state, Py_ssize_t pos, int + folded_pos) { + int (*full_case_fold)(RE_LocaleInfo* locale_info, Py_UCS4 ch, Py_UCS4* + folded); + Py_UCS4 folded[RE_MAX_FOLDED]; + + full_case_fold = state->encoding->full_case_fold; + + full_case_fold(state->locale_info, state->char_at(state->text, pos), + folded); + + return folded[folded_pos]; +} + +/* Does the test of a FUZZY_EXT for a folded group. */ +Py_LOCAL_INLINE(BOOL) fuzzy_ext_match_group_fld(RE_State* state, RE_Node* + fuzzy_node, int folded_pos) { + RE_Node* test_node; + + test_node = fuzzy_node->nonstring.next_2.node; + if (!test_node) + return TRUE; + + switch (test_node->op) { + case RE_OP_CHARACTER: + return state->text_pos < state->slice_end && + matches_CHARACTER(state->encoding, state->locale_info, test_node, + folded_char_at(state, state->text_pos, folded_pos)) == + test_node->match; + case RE_OP_CHARACTER_IGN: + return state->text_pos < state->slice_end && + matches_CHARACTER_IGN(state->encoding, state->locale_info, test_node, + folded_char_at(state, state->text_pos, folded_pos)) == + test_node->match; + case RE_OP_CHARACTER_IGN_REV: + return state->text_pos > state->slice_start && + matches_CHARACTER_IGN(state->encoding, state->locale_info, test_node, + folded_char_at(state, state->text_pos - 1, folded_pos - 1)) == + test_node->match; + case RE_OP_CHARACTER_REV: + return state->text_pos > state->slice_start && + matches_CHARACTER(state->encoding, state->locale_info, test_node, + folded_char_at(state, state->text_pos - 1, folded_pos - 1)) == + test_node->match; + case RE_OP_PROPERTY: + return state->text_pos < state->slice_end && + matches_PROPERTY(state->encoding, state->locale_info, test_node, + folded_char_at(state, state->text_pos, folded_pos)) == + test_node->match; + case RE_OP_PROPERTY_IGN: + return state->text_pos < state->slice_end && + matches_PROPERTY_IGN(state->encoding, state->locale_info, test_node, + folded_char_at(state, state->text_pos, folded_pos)) == + test_node->match; + case RE_OP_PROPERTY_IGN_REV: + return state->text_pos > state->slice_start && + matches_PROPERTY_IGN(state->encoding, state->locale_info, test_node, + folded_char_at(state, state->text_pos - 1, folded_pos - 1)) == + test_node->match; + case RE_OP_PROPERTY_REV: + return state->text_pos > state->slice_start && + matches_PROPERTY(state->encoding, state->locale_info, test_node, + folded_char_at(state, state->text_pos - 1, folded_pos - 1)) == + test_node->match; + case RE_OP_RANGE: + return state->text_pos < state->slice_end && + matches_RANGE(state->encoding, state->locale_info, test_node, + folded_char_at(state, state->text_pos, folded_pos)) == + test_node->match; + case RE_OP_RANGE_IGN: + return state->text_pos < state->slice_end && + matches_RANGE_IGN(state->encoding, state->locale_info, test_node, + folded_char_at(state, state->text_pos, folded_pos)) == + test_node->match; + case RE_OP_RANGE_IGN_REV: + return state->text_pos > state->slice_start && + matches_RANGE_IGN(state->encoding, state->locale_info, test_node, + folded_char_at(state, state->text_pos - 1, folded_pos - 1)) == + test_node->match; + case RE_OP_RANGE_REV: + return state->text_pos > state->slice_start && + matches_RANGE(state->encoding, state->locale_info, test_node, + folded_char_at(state, state->text_pos - 1, folded_pos - 1)) == + test_node->match; + case RE_OP_SET_DIFF: + case RE_OP_SET_INTER: + case RE_OP_SET_SYM_DIFF: + case RE_OP_SET_UNION: + return state->text_pos < state->slice_end && + matches_SET(state->encoding, state->locale_info, test_node, + folded_char_at(state, state->text_pos, folded_pos)) == + test_node->match; + } + + return TRUE; +} + +/* Checks a fuzzy match of an item. */ +Py_LOCAL_INLINE(int) next_fuzzy_match_item(RE_State* state, RE_FuzzyData* data, + BOOL is_string, RE_INT8 step) { + Py_ssize_t new_pos; + + if (!this_error_permitted(state, data->fuzzy_type)) + return RE_ERROR_FAILURE; + + data->new_text_pos = state->text_pos; + + switch (data->fuzzy_type) { + case RE_FUZZY_DEL: + /* Could a character at text_pos have been deleted? */ + if (step == 0) + return RE_ERROR_FAILURE; + + if (is_string) + data->new_string_pos += step; + else + data->new_node = data->new_node->next_1.node; + + return RE_ERROR_SUCCESS; + case RE_FUZZY_INS: + /* Could the character at text_pos have been inserted? */ + if (!data->permit_insertion) + return RE_ERROR_FAILURE; + + if (step == 0) + new_pos = data->new_text_pos + data->step; + else + new_pos = data->new_text_pos + step; + + if (state->slice_start <= new_pos && new_pos <= state->slice_end) { + if (!fuzzy_ext_match(state, state->fuzzy_node, data->new_text_pos)) + return RE_ERROR_FAILURE; + + data->new_text_pos = new_pos; + + return RE_ERROR_SUCCESS; + } + + return check_fuzzy_partial(state, data->new_text_pos); + case RE_FUZZY_SUB: + /* Could the character at text_pos have been substituted? */ + if (step == 0) + return RE_ERROR_FAILURE; + + new_pos = data->new_text_pos + step; + + if (state->slice_start <= new_pos && new_pos <= state->slice_end) { + if (!fuzzy_ext_match(state, state->fuzzy_node, data->new_text_pos)) + return RE_ERROR_FAILURE; + + data->new_text_pos = new_pos; + + if (is_string) + data->new_string_pos += step; + else + data->new_node = data->new_node->next_1.node; + + return RE_ERROR_SUCCESS; + } + + return check_fuzzy_partial(state, new_pos); + } + + return RE_ERROR_FAILURE; +} + +/* Tries a fuzzy match of an item of width 0 or 1. */ +Py_LOCAL_INLINE(int) fuzzy_match_item(RE_State* state, BOOL search, RE_Node** + node, RE_INT8 step) { + size_t* fuzzy_counts; + RE_FuzzyData data; + TRACE(("<>\n")) + + fuzzy_counts = state->fuzzy_counts; + + if (!any_error_permitted(state)) { + TRACE((" return RE_ERROR_FAILURE\n")) + return RE_ERROR_FAILURE; + } + + data.new_node = *node; + + if (step == 0) { + if (data.new_node->status & RE_STATUS_REVERSE) { + data.step = -1; + data.limit = state->slice_start; + } else { + data.step = 1; + data.limit = state->slice_end; + } + } else + data.step = step; + + /* Permit insertion except initially when searching (it's better just to + * start searching one character later). + */ + data.permit_insertion = !search || state->text_pos != state->search_anchor; + + for (data.fuzzy_type = 0; data.fuzzy_type < RE_FUZZY_COUNT; + data.fuzzy_type++) { + int status; + + status = next_fuzzy_match_item(state, &data, FALSE, step); + if (status < 0) + return status; + + if (status == RE_ERROR_SUCCESS) + goto found; + } + + TRACE((" return RE_ERROR_FAILURE\n")) + return RE_ERROR_FAILURE; + +found: + if (!push_pointer(state, &state->bstack, *node)) + return RE_ERROR_MEMORY; + if (!push_int8(state, &state->bstack, step)) + return RE_ERROR_MEMORY; + if (!push_ssize(state, &state->bstack, state->text_pos)) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, data.fuzzy_type)) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, (*node)->op)) + return RE_ERROR_MEMORY; + + /* bstack: node step text_pos fuzzy_type op */ + + if (!record_fuzzy(state, data.fuzzy_type, data.fuzzy_type == RE_FUZZY_DEL ? + data.new_text_pos : data.new_text_pos - data.step)) + return RE_ERROR_MEMORY; + + ++fuzzy_counts[data.fuzzy_type]; + ++state->capture_change; + + state->text_pos = data.new_text_pos; + *node = data.new_node; + + TRACE((" fuzzy_counts is (%zd, %zd, %zd)\n", fuzzy_counts[0], + fuzzy_counts[1], fuzzy_counts[2])) + TRACE((" return RE_ERROR_SUCCESS\n")) + return RE_ERROR_SUCCESS; +} + +/* Retries a fuzzy match of a item of width 0 or 1. */ +Py_LOCAL_INLINE(int) retry_fuzzy_match_item(RE_State* state, RE_UINT8 op, BOOL + search, RE_Node** node, BOOL advance) { + size_t* fuzzy_counts; + RE_FuzzyData data; + RE_INT8 step; + RE_Node* curr_node; + TRACE(("<>\n")) + + fuzzy_counts = state->fuzzy_counts; + + unrecord_fuzzy(state); + + /* bstack: node step text_pos fuzzy_type */ + + if (!pop_uint8(state, &state->bstack, &data.fuzzy_type)) + return RE_ERROR_MEMORY; + if (!pop_ssize(state, &state->bstack, &state->text_pos)) + return RE_ERROR_MEMORY; + if (!pop_int8(state, &state->bstack, &step)) + return RE_ERROR_MEMORY; + if (!pop_pointer(state, &state->bstack, (void*)&curr_node)) + return RE_ERROR_MEMORY; + + data.new_node = curr_node; + data.step = step; + + /* bstack: - */ + + if (data.fuzzy_type >= 0) + --fuzzy_counts[data.fuzzy_type]; + + /* Permit insertion except initially when searching (it's better just to + * start searching one character later). + */ + data.permit_insertion = !search || state->text_pos != state->search_anchor; + + step = advance ? data.step : 0; + + for (++data.fuzzy_type; data.fuzzy_type < RE_FUZZY_COUNT; + data.fuzzy_type++) { + int status; + + status = next_fuzzy_match_item(state, &data, FALSE, step); + if (status < 0) + return status; + + if (status == RE_ERROR_SUCCESS) + goto found; + } + + TRACE((" return RE_ERROR_FAILURE\n")) + return RE_ERROR_FAILURE; + +found: + if (!push_pointer(state, &state->bstack, curr_node)) + return RE_ERROR_MEMORY; + if (!push_int8(state, &state->bstack, step)) + return RE_ERROR_MEMORY; + if (!push_ssize(state, &state->bstack, state->text_pos)) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, data.fuzzy_type)) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, op)) + return RE_ERROR_MEMORY; + + /* bstack: node step text_pos fuzzy_type op */ + + if (!record_fuzzy(state, data.fuzzy_type, data.fuzzy_type == RE_FUZZY_DEL ? + data.new_text_pos : data.new_text_pos - data.step)) + return RE_ERROR_MEMORY; + + ++fuzzy_counts[data.fuzzy_type]; + ++state->capture_change; + + state->text_pos = data.new_text_pos; + *node = data.new_node; + + TRACE((" fuzzy_counts is (%zd, %zd, %zd)\n", fuzzy_counts[0], + fuzzy_counts[1], fuzzy_counts[2])) + TRACE((" return RE_ERROR_SUCCESS\n")) + return RE_ERROR_SUCCESS; +} + +/* Tries a fuzzy insertion of characters, initially 0, after a string. */ +Py_LOCAL_INLINE(int) fuzzy_insert(RE_State* state, int step, RE_Node* node) { + Py_ssize_t limit; + + limit = step > 0 ? state->slice_end : state->slice_start; + + if (state->text_pos == limit || !insertion_permitted(state, + state->fuzzy_node, state->fuzzy_counts)) + return RE_ERROR_SUCCESS; + + if (!push_int8(state, &state->bstack, (RE_INT8)step)) + return RE_ERROR_MEMORY; + if (!push_ssize(state, &state->bstack, state->text_pos)) + return RE_ERROR_MEMORY; + if (!push_ssize(state, &state->bstack, 0)) + return RE_ERROR_MEMORY; + if (!push_pointer(state, &state->bstack, node)) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, RE_OP_FUZZY_INSERT)) + return RE_ERROR_MEMORY; + + /* bstack: step text_pos count node FUZZY_INSERT */ + + return RE_ERROR_SUCCESS; +} + +/* Retries a fuzzy insertion of characters after a string. */ +Py_LOCAL_INLINE(int) retry_fuzzy_insert(RE_State* state, RE_Node** node) { + RE_Node* curr_node; + Py_ssize_t count; + RE_INT8 step; + Py_ssize_t limit; + + /* bstack: step text_pos count node */ + + if (!pop_pointer(state, &state->bstack, (void*)&curr_node)) + return RE_ERROR_MEMORY; + if (!pop_ssize(state, &state->bstack, &count)) + return RE_ERROR_MEMORY; + if (!pop_ssize(state, &state->bstack, &state->text_pos)) + return RE_ERROR_MEMORY; + if (!pop_int8(state, &state->bstack, &step)) + return RE_ERROR_MEMORY; + + limit = step > 0 ? state->slice_end : state->slice_start; + + if (state->text_pos == limit || !insertion_permitted(state, + state->fuzzy_node, state->fuzzy_counts) || !fuzzy_ext_match(state, + state->fuzzy_node, state->text_pos)) { + while (count > 0) { + unrecord_fuzzy(state); + --state->fuzzy_counts[RE_FUZZY_INS]; + --count; + } + + return RE_ERROR_FAILURE; + } + + state->text_pos += step; + ++count; + + if (!push_int8(state, &state->bstack, step)) + return RE_ERROR_MEMORY; + if (!push_ssize(state, &state->bstack, state->text_pos)) + return RE_ERROR_MEMORY; + if (!push_ssize(state, &state->bstack, count)) + return RE_ERROR_MEMORY; + if (!push_pointer(state, &state->bstack, curr_node)) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, RE_OP_FUZZY_INSERT)) + return RE_ERROR_MEMORY; + + /* bstack: step text_pos count node FUZZY_INSERT */ + + if (!record_fuzzy(state, RE_FUZZY_INS, state->text_pos - step)) + return RE_ERROR_MEMORY; + + ++state->fuzzy_counts[RE_FUZZY_INS]; + ++state->capture_change; + + *node = curr_node; + + return RE_ERROR_SUCCESS; +} + +/* Tries a fuzzy match of a string. */ +Py_LOCAL_INLINE(int) fuzzy_match_string(RE_State* state, BOOL search, RE_Node* + node, Py_ssize_t* string_pos, RE_INT8 step) { + size_t* fuzzy_counts; + RE_FuzzyData data; + TRACE(("<>\n")) + + fuzzy_counts = state->fuzzy_counts; + + if (!any_error_permitted(state)) { + TRACE((" return RE_ERROR_FAILURE\n")) + return RE_ERROR_FAILURE; + } + + data.new_string_pos = *string_pos; + data.step = step; + + /* Permit insertion except initially when searching (it's better just to + * start searching one character later). + */ + data.permit_insertion = !search || state->text_pos != state->search_anchor; + + for (data.fuzzy_type = 0; data.fuzzy_type < RE_FUZZY_COUNT; + data.fuzzy_type++) { + int status; + + status = next_fuzzy_match_item(state, &data, TRUE, data.step); + if (status < 0) + return status; + + if (status == RE_ERROR_SUCCESS) + goto found; + } + + TRACE((" return RE_ERROR_FAILURE\n")) + return RE_ERROR_FAILURE; + +found: + if (!push_pointer(state, &state->bstack, node)) + return RE_ERROR_MEMORY; + if (!push_int8(state, &state->bstack, step)) + return RE_ERROR_MEMORY; + if (!push_ssize(state, &state->bstack, *string_pos)) + return RE_ERROR_MEMORY; + if (!push_ssize(state, &state->bstack, state->text_pos)) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, data.fuzzy_type)) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, node->op)) + return RE_ERROR_MEMORY; + + /* bstack: node step string_pos text_pos fuzzy_type op */ + + if (!record_fuzzy(state, data.fuzzy_type, state->text_pos)) + return RE_ERROR_MEMORY; + + ++fuzzy_counts[data.fuzzy_type]; + ++state->capture_change; + + state->text_pos = data.new_text_pos; + *string_pos = data.new_string_pos; + + TRACE((" fuzzy_counts is (%zd, %zd, %zd)\n", fuzzy_counts[0], + fuzzy_counts[1], fuzzy_counts[2])) + TRACE((" return RE_ERROR_SUCCESS\n")) + return RE_ERROR_SUCCESS; +} + +/* Retries a fuzzy match of a string. */ +Py_LOCAL_INLINE(int) retry_fuzzy_match_string(RE_State* state, RE_UINT8 op, + BOOL search, RE_Node** node, Py_ssize_t* string_pos) { + size_t* fuzzy_counts; + RE_FuzzyData data; + RE_Node* new_node; + TRACE(("<>\n")) + + fuzzy_counts = state->fuzzy_counts; + + unrecord_fuzzy(state); + + /* bstack: node step string_pos text_pos fuzzy_type */ + + if (!pop_uint8(state, &state->bstack, &data.fuzzy_type)) + return RE_ERROR_MEMORY; + if (!pop_ssize(state, &state->bstack, &state->text_pos)) + return RE_ERROR_MEMORY; + if (!pop_ssize(state, &state->bstack, string_pos)) + return RE_ERROR_MEMORY; + if (!pop_int8(state, &state->bstack, &data.step)) + return RE_ERROR_MEMORY; + if (!pop_pointer(state, &state->bstack, (void*)&new_node)) + return RE_ERROR_MEMORY; + + data.new_string_pos = *string_pos; + + --fuzzy_counts[data.fuzzy_type]; + + /* Permit insertion except initially when searching (it's better just to + * start searching one character later). + */ + data.permit_insertion = !search || state->text_pos != state->search_anchor; + + for (++data.fuzzy_type; data.fuzzy_type < RE_FUZZY_COUNT; + data.fuzzy_type++) { + int status; + + status = next_fuzzy_match_item(state, &data, TRUE, data.step); + if (status < 0) + return status; + + if (status == RE_ERROR_SUCCESS) + goto found; + } + + TRACE((" return RE_ERROR_FAILURE\n")) + return RE_ERROR_FAILURE; + +found: + if (!push_pointer(state, &state->bstack, new_node)) + return RE_ERROR_MEMORY; + if (!push_int8(state, &state->bstack, data.step)) + return RE_ERROR_MEMORY; + if (!push_ssize(state, &state->bstack, *string_pos)) + return RE_ERROR_MEMORY; + if (!push_ssize(state, &state->bstack, state->text_pos)) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, data.fuzzy_type)) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, op)) + return RE_ERROR_MEMORY; + + if (!record_fuzzy(state, data.fuzzy_type, state->text_pos)) + return RE_ERROR_MEMORY; + + /* bstack: node step string_pos text_pos fuzzy_type op */ + + ++fuzzy_counts[data.fuzzy_type]; + ++state->capture_change; + + state->text_pos = data.new_text_pos; + *node = new_node; + *string_pos = data.new_string_pos; + + TRACE((" fuzzy_counts is (%zd, %zd, %zd)\n", fuzzy_counts[0], + fuzzy_counts[1], fuzzy_counts[2])) + TRACE((" return RE_ERROR_SUCCESS\n")) + return RE_ERROR_SUCCESS; +} + +/* Checks a fuzzy match of a atring. */ +Py_LOCAL_INLINE(int) next_fuzzy_match_string_fld(RE_State* state, RE_FuzzyData* + data) { + int new_pos; + + if (!this_error_permitted(state, data->fuzzy_type)) + return RE_ERROR_FAILURE; + + data->new_text_pos = state->text_pos; + + switch (data->fuzzy_type) { + case RE_FUZZY_DEL: + /* Could a character at text_pos have been deleted? */ + data->new_string_pos += data->step; + + return RE_ERROR_SUCCESS; + case RE_FUZZY_INS: + /* Could the character at text_pos have been inserted? */ + if (!data->permit_insertion) + return RE_ERROR_FAILURE; + + new_pos = data->new_folded_pos + data->step; + + if (0 <= new_pos && new_pos <= data->folded_len) { + if (!fuzzy_ext_match(state, state->fuzzy_node, + data->new_string_pos)) + return RE_ERROR_FAILURE; + + data->new_folded_pos = new_pos; + + return RE_ERROR_SUCCESS; + } + + return check_fuzzy_partial(state, new_pos); + case RE_FUZZY_SUB: + /* Could the character at text_pos have been substituted? */ + new_pos = data->new_folded_pos + data->step; + + if (0 <= new_pos && new_pos <= data->folded_len) { + if (!fuzzy_ext_match(state, state->fuzzy_node, + data->new_string_pos)) + return RE_ERROR_FAILURE; + + data->new_folded_pos = new_pos; + data->new_string_pos += data->step; + + return RE_ERROR_SUCCESS; + } + + return check_fuzzy_partial(state, new_pos); + } + + return RE_ERROR_FAILURE; +} + +/* Tries a fuzzy match of a string, ignoring case. */ +Py_LOCAL_INLINE(int) fuzzy_match_string_fld(RE_State* state, BOOL search, + RE_Node* node, Py_ssize_t* string_pos, int* folded_pos, int folded_len, + RE_INT8 step) { + size_t* fuzzy_counts; + RE_FuzzyData data; + TRACE(("<>\n")) + + fuzzy_counts = state->fuzzy_counts; + + if (!any_error_permitted(state)) { + TRACE((" return RE_ERROR_FAILURE\n")) + return RE_ERROR_FAILURE; + } + + data.new_string_pos = *string_pos; + data.new_folded_pos = *folded_pos; + data.folded_len = folded_len; + data.step = step; + + /* Permit insertion except initially when searching (it's better just to + * start searching one character later). + */ + data.permit_insertion = !search || state->text_pos != state->search_anchor; + + if (step > 0) { + if (data.new_folded_pos != 0) + data.permit_insertion = RE_ERROR_SUCCESS; + } else { + if (data.new_folded_pos != folded_len) + data.permit_insertion = RE_ERROR_SUCCESS; + } + + for (data.fuzzy_type = 0; data.fuzzy_type < RE_FUZZY_COUNT; + data.fuzzy_type++) { + int status; + + status = next_fuzzy_match_string_fld(state, &data); + if (status < 0) + return status; + + if (status == RE_ERROR_SUCCESS) + goto found; + } + + TRACE((" return RE_ERROR_FAILURE\n")) + return RE_ERROR_FAILURE; + +found: + if (!push_pointer(state, &state->bstack, node)) + return RE_ERROR_MEMORY; + if (!push_int8(state, &state->bstack, step)) + return RE_ERROR_MEMORY; + if (!push_ssize(state, &state->bstack, *string_pos)) + return RE_ERROR_MEMORY; + if (!push_int(state, &state->bstack, *folded_pos)) + return RE_ERROR_MEMORY; + if (!push_int(state, &state->bstack, folded_len)) + return RE_ERROR_MEMORY; + if (!push_ssize(state, &state->bstack, state->text_pos)) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, data.fuzzy_type)) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, node->op)) + return RE_ERROR_MEMORY; + + /* bstack: node step string_pos folded_pos folded_len text_pos fuzzy_type + * op + */ + + if (!record_fuzzy(state, data.fuzzy_type, state->text_pos)) + return RE_ERROR_MEMORY; + + ++fuzzy_counts[data.fuzzy_type]; + ++state->capture_change; + + state->text_pos = data.new_text_pos; + *string_pos = data.new_string_pos; + *folded_pos = data.new_folded_pos; + + TRACE((" fuzzy_counts is (%zd, %zd, %zd)\n", fuzzy_counts[0], + fuzzy_counts[1], fuzzy_counts[2])) + TRACE((" return RE_ERROR_SUCCESS\n")) + return RE_ERROR_SUCCESS; +} + +/* Retries a fuzzy match of a string, ignoring case. */ +Py_LOCAL_INLINE(int) retry_fuzzy_match_string_fld(RE_State* state, RE_UINT8 op, + BOOL search, RE_Node** node, Py_ssize_t* string_pos, int* folded_pos) { + size_t* fuzzy_counts; + RE_FuzzyData data; + int curr_folded_pos; + RE_Node* new_node; + TRACE(("<>\n")) + + fuzzy_counts = state->fuzzy_counts; + + unrecord_fuzzy(state); + + /* bstack: node step string_pos folded_pos folded_len text_pos fuzzy_type + */ + + if (!pop_uint8(state, &state->bstack, &data.fuzzy_type)) + return RE_ERROR_MEMORY; + if (!pop_ssize(state, &state->bstack, &state->text_pos)) + return RE_ERROR_MEMORY; + if (!pop_int(state, &state->bstack, &data.folded_len)) + return RE_ERROR_MEMORY; + if (!pop_int(state, &state->bstack, &curr_folded_pos)) + return RE_ERROR_MEMORY; + if (!pop_ssize(state, &state->bstack, string_pos)) + return RE_ERROR_MEMORY; + if (!pop_int8(state, &state->bstack, &data.step)) + return RE_ERROR_MEMORY; + if (!pop_pointer(state, &state->bstack, (void*)&new_node)) + return RE_ERROR_MEMORY; + + data.new_string_pos = *string_pos; + data.new_folded_pos = curr_folded_pos; + + --fuzzy_counts[data.fuzzy_type]; + + /* Permit insertion except initially when searching (it's better just to + * start searching one character later). + */ + data.permit_insertion = !search || state->text_pos != state->search_anchor; + + if (data.step > 0) { + if (data.new_folded_pos != 0) + data.permit_insertion = RE_ERROR_SUCCESS; + } else { + if (data.new_folded_pos != data.folded_len) + data.permit_insertion = RE_ERROR_SUCCESS; + } + + for (++data.fuzzy_type; data.fuzzy_type < RE_FUZZY_COUNT; + data.fuzzy_type++) { + int status; + + status = next_fuzzy_match_string_fld(state, &data); + if (status < 0) + return status; + + if (status == RE_ERROR_SUCCESS) + goto found; + } + + TRACE((" return RE_ERROR_FAILURE\n")) + return RE_ERROR_FAILURE; + +found: + if (!push_pointer(state, &state->bstack, new_node)) + return RE_ERROR_MEMORY; + if (!push_int8(state, &state->bstack, data.step)) + return RE_ERROR_MEMORY; + if (!push_ssize(state, &state->bstack, *string_pos)) + return RE_ERROR_MEMORY; + if (!push_int(state, &state->bstack, curr_folded_pos)) + return RE_ERROR_MEMORY; + if (!push_int(state, &state->bstack, data.folded_len)) + return RE_ERROR_MEMORY; + if (!push_ssize(state, &state->bstack, state->text_pos)) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, data.fuzzy_type)) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, op)) + return RE_ERROR_MEMORY; + + if (!record_fuzzy(state, data.fuzzy_type, state->text_pos)) + return RE_ERROR_MEMORY; + + /* bstack: node step string_pos folded_pos folded_len text_pos fuzzy_type + * op + */ + + ++fuzzy_counts[data.fuzzy_type]; + ++state->capture_change; + + state->text_pos = data.new_text_pos; + *node = new_node; + *string_pos = data.new_string_pos; + *folded_pos = data.new_folded_pos; + + TRACE((" fuzzy_counts is (%zd, %zd, %zd)\n", fuzzy_counts[0], + fuzzy_counts[1], fuzzy_counts[2])) + TRACE((" return RE_ERROR_SUCCESS\n")) + return RE_ERROR_SUCCESS; +} + +/* Checks a fuzzy match of a atring. */ +Py_LOCAL_INLINE(int) next_fuzzy_match_group_fld(RE_State* state, RE_FuzzyData* + data) { + int new_pos; + + if (!this_error_permitted(state, data->fuzzy_type)) + return RE_ERROR_FAILURE; + + data->new_text_pos = state->text_pos; + + switch (data->fuzzy_type) { + case RE_FUZZY_DEL: + /* Could a character at text_pos have been deleted? */ + data->new_gfolded_pos += data->step; + + return RE_ERROR_SUCCESS; + case RE_FUZZY_INS: + /* Could the character at text_pos have been inserted? */ + if (!data->permit_insertion) + return RE_ERROR_FAILURE; + + new_pos = data->new_folded_pos + data->step; + + if (0 <= new_pos && new_pos <= data->folded_len) { + if (!fuzzy_ext_match_group_fld(state, state->fuzzy_node, + data->new_folded_pos)) + return RE_ERROR_FAILURE; + + data->new_folded_pos = new_pos; + + return RE_ERROR_SUCCESS; + } + + return check_fuzzy_partial(state, new_pos); + case RE_FUZZY_SUB: + /* Could the character at text_pos have been substituted? */ + new_pos = data->new_folded_pos + data->step; + + if (0 <= new_pos && new_pos <= data->folded_len) { + if (!fuzzy_ext_match_group_fld(state, state->fuzzy_node, + data->new_folded_pos)) + return RE_ERROR_FAILURE; + + data->new_folded_pos = new_pos; + data->new_gfolded_pos += data->step; + + return RE_ERROR_SUCCESS; + } + + return check_fuzzy_partial(state, new_pos); + } + + return RE_ERROR_FAILURE; +} + +/* Tries a fuzzy match of a group reference, ignoring case. */ +Py_LOCAL_INLINE(int) fuzzy_match_group_fld(RE_State* state, BOOL search, + RE_Node* node, int* folded_pos, int folded_len, Py_ssize_t* group_pos, int* + gfolded_pos, int gfolded_len, RE_INT8 step) { + size_t* fuzzy_counts; + RE_FuzzyData data; + Py_ssize_t new_group_pos; + TRACE(("<>\n")) + + fuzzy_counts = state->fuzzy_counts; + + if (!any_error_permitted(state)) { + TRACE((" return RE_ERROR_FAILURE\n")) + return RE_ERROR_FAILURE; + } + + data.new_folded_pos = *folded_pos; + data.folded_len = folded_len; + new_group_pos = *group_pos; + data.new_gfolded_pos = *gfolded_pos; + data.step = step; + + /* Permit insertion except initially when searching (it's better just to + * start searching one character later). + */ + data.permit_insertion = !search || state->text_pos != state->search_anchor; + + if (data.step > 0) { + if (data.new_folded_pos != 0) + data.permit_insertion = RE_ERROR_SUCCESS; + } else { + if (data.new_folded_pos != folded_len) + data.permit_insertion = RE_ERROR_SUCCESS; + } + + for (data.fuzzy_type = 0; data.fuzzy_type < RE_FUZZY_COUNT; + data.fuzzy_type++) { + int status; + + status = next_fuzzy_match_group_fld(state, &data); + if (status < 0) + return status; + + if (status == RE_ERROR_SUCCESS) + goto found; + } + + TRACE((" return RE_ERROR_FAILURE\n")) + return RE_ERROR_FAILURE; + +found: + if (!push_pointer(state, &state->bstack, node)) + return RE_ERROR_MEMORY; + if (!push_int8(state, &state->bstack, step)) + return RE_ERROR_MEMORY; + if (!push_int(state, &state->bstack, *gfolded_pos)) + return RE_ERROR_MEMORY; + if (!push_int(state, &state->bstack, gfolded_len)) + return RE_ERROR_MEMORY; + if (!push_ssize(state, &state->bstack, *group_pos)) + return RE_ERROR_MEMORY; + if (!push_int(state, &state->bstack, *folded_pos)) + return RE_ERROR_MEMORY; + if (!push_int(state, &state->bstack, folded_len)) + return RE_ERROR_MEMORY; + if (!push_ssize(state, &state->bstack, state->text_pos)) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, data.fuzzy_type)) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, node->op)) + return RE_ERROR_MEMORY; + + /* bstack: node step gfolded_pos gfolded_len group_pos folded_pos + * folded_len text_pos fuzzy_type op + */ + + if (!record_fuzzy(state, data.fuzzy_type, state->text_pos)) + return RE_ERROR_MEMORY; + + ++fuzzy_counts[data.fuzzy_type]; + ++state->capture_change; + + state->text_pos = data.new_text_pos; + *group_pos = new_group_pos; + *folded_pos = data.new_folded_pos; + *gfolded_pos = data.new_gfolded_pos; + + TRACE((" fuzzy_counts is (%zd, %zd, %zd)\n", fuzzy_counts[0], + fuzzy_counts[1], fuzzy_counts[2])) + TRACE((" return RE_ERROR_SUCCESS\n")) + return RE_ERROR_SUCCESS; +} + +/* Retries a fuzzy match of a group reference, ignoring case. */ +Py_LOCAL_INLINE(int) retry_fuzzy_match_group_fld(RE_State* state, RE_UINT8 op, + BOOL search, RE_Node** node, int* folded_pos, Py_ssize_t* group_pos, int* + gfolded_pos) { + size_t* fuzzy_counts; + RE_FuzzyData data; + int new_folded_pos; + Py_ssize_t new_group_pos; + int gfolded_len; + int new_gfolded_pos; + RE_Node* new_node; + TRACE(("<>\n")) + + fuzzy_counts = state->fuzzy_counts; + + unrecord_fuzzy(state); + + /* bstack: node step gfolded_pos gfolded_len group_pos folded_pos + * folded_len text_pos fuzzy_type + */ + + if (!pop_uint8(state, &state->bstack, &data.fuzzy_type)) + return RE_ERROR_MEMORY; + if (!pop_ssize(state, &state->bstack, &state->text_pos)) + return RE_ERROR_MEMORY; + if (!pop_int(state, &state->bstack, &data.folded_len)) + return RE_ERROR_MEMORY; + if (!pop_int(state, &state->bstack, &new_folded_pos)) + return RE_ERROR_MEMORY; + if (!pop_ssize(state, &state->bstack, &new_group_pos)) + return RE_ERROR_MEMORY; + if (!pop_int(state, &state->bstack, &gfolded_len)) + return RE_ERROR_MEMORY; + if (!pop_int(state, &state->bstack, &new_gfolded_pos)) + return RE_ERROR_MEMORY; + if (!pop_int8(state, &state->bstack, &data.step)) + return RE_ERROR_MEMORY; + if (!pop_pointer(state, &state->bstack, (void*)&new_node)) + return RE_ERROR_MEMORY; + + data.new_folded_pos = new_folded_pos; + data.new_gfolded_pos = new_gfolded_pos; + + --fuzzy_counts[data.fuzzy_type]; + + /* Permit insertion except initially when searching (it's better just to + * start searching one character later). + */ + data.permit_insertion = !search || state->text_pos != state->search_anchor + || data.new_folded_pos != data.folded_len; + + for (++data.fuzzy_type; data.fuzzy_type < RE_FUZZY_COUNT; + data.fuzzy_type++) { + int status; + + status = next_fuzzy_match_group_fld(state, &data); + if (status < 0) + return status; + + if (status == RE_ERROR_SUCCESS) + goto found; + } + + TRACE((" return RE_ERROR_FAILURE\n")) + return RE_ERROR_FAILURE; + +found: + if (!push_pointer(state, &state->bstack, new_node)) + return RE_ERROR_MEMORY; + if (!push_int8(state, &state->bstack, data.step)) + return RE_ERROR_MEMORY; + if (!push_int(state, &state->bstack, new_gfolded_pos)) + return RE_ERROR_MEMORY; + if (!push_int(state, &state->bstack, gfolded_len)) + return RE_ERROR_MEMORY; + if (!push_ssize(state, &state->bstack, new_group_pos)) + return RE_ERROR_MEMORY; + if (!push_int(state, &state->bstack, new_folded_pos)) + return RE_ERROR_MEMORY; + if (!push_int(state, &state->bstack, data.folded_len)) + return RE_ERROR_MEMORY; + if (!push_ssize(state, &state->bstack, state->text_pos)) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, data.fuzzy_type)) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, op)) + return RE_ERROR_MEMORY; + + if (!record_fuzzy(state, data.fuzzy_type, state->text_pos)) + return RE_ERROR_MEMORY; + + /* bstack: node step gfolded_pos gfolded_len group_pos folded_pos + * folded_len text_pos fuzzy_type op + */ + + ++fuzzy_counts[data.fuzzy_type]; + ++state->capture_change; + + state->text_pos = data.new_text_pos; + *node = new_node; + *group_pos = new_group_pos; + *folded_pos = data.new_folded_pos; + *gfolded_pos = data.new_gfolded_pos; + + TRACE((" fuzzy_counts is (%zd, %zd, %zd)\n", fuzzy_counts[0], + fuzzy_counts[1], fuzzy_counts[2])) + TRACE((" return RE_ERROR_SUCCESS\n")) + return RE_ERROR_SUCCESS; +} + +/* Locates the required string, if there's one. */ +Py_LOCAL_INLINE(Py_ssize_t) locate_required_string(RE_State* state, BOOL + search) { + PatternObject* pattern; + Py_ssize_t found_pos; + Py_ssize_t end_pos; + + pattern = state->pattern; + + if (!pattern->req_string) + /* There isn't a required string, so start matching from the current + * position. + */ + return state->text_pos; + + /* Search for the required string and calculate where to start matching. */ + switch (pattern->req_string->op) { + case RE_OP_STRING: + { + BOOL is_partial; + Py_ssize_t limit; + + if (search || pattern->req_offset < 0) + limit = state->slice_end; + else { + limit = state->slice_start + pattern->req_offset + + (Py_ssize_t)pattern->req_string->value_count; + if (limit > state->slice_end) + limit = state->slice_end; + } + + if (state->req_pos < 0 || state->text_pos > state->req_pos) + /* First time or already passed it. */ + found_pos = string_search(state, pattern->req_string, + state->text_pos, limit, TRUE, &is_partial); + else { + found_pos = state->req_pos; + end_pos = state->req_end; + is_partial = FALSE; + } + + if (found_pos < 0) + /* The required string wasn't found. */ + return -1; + + if (!is_partial) { + /* Record where the required string matched. */ + state->req_pos = found_pos; + state->req_end = found_pos + + (Py_ssize_t)pattern->req_string->value_count; + } + + if (pattern->req_offset >= 0) { + /* Step back from the required string to where we should start + * matching. + */ + found_pos -= pattern->req_offset; + if (found_pos >= state->text_pos) + return found_pos; + } + break; + } + case RE_OP_STRING_FLD: + { + BOOL is_partial; + Py_ssize_t limit; + + if (search || pattern->req_offset < 0) + limit = state->slice_end; + else { + limit = state->slice_start + pattern->req_offset + + (Py_ssize_t)pattern->req_string->value_count; + if (limit > state->slice_end) + limit = state->slice_end; + } + + if (state->req_pos < 0 || state->text_pos > state->req_pos) + /* First time or already passed it. */ + found_pos = string_search_fld(state, pattern->req_string, + state->text_pos, limit, &end_pos, &is_partial); + else { + found_pos = state->req_pos; + end_pos = state->req_end; + is_partial = FALSE; + } + + if (found_pos < 0) + /* The required string wasn't found. */ + return -1; + + if (!is_partial) { + /* Record where the required string matched. */ + state->req_pos = found_pos; + state->req_end = end_pos; + } + + if (pattern->req_offset >= 0) { + /* Step back from the required string to where we should start + * matching. + */ + found_pos -= pattern->req_offset; + if (found_pos >= state->text_pos) + return found_pos; + } + break; + } + case RE_OP_STRING_FLD_REV: + { + BOOL is_partial; + Py_ssize_t limit; + + if (search || pattern->req_offset < 0) + limit = state->slice_start; + else { + limit = state->slice_end - pattern->req_offset - + (Py_ssize_t)pattern->req_string->value_count; + if (limit < state->slice_start) + limit = state->slice_start; + } + + if (state->req_pos < 0 || state->text_pos < state->req_pos) + /* First time or already passed it. */ + found_pos = string_search_fld_rev(state, pattern->req_string, + state->text_pos, limit, &end_pos, &is_partial); + else { + found_pos = state->req_pos; + end_pos = state->req_end; + is_partial = FALSE; + } + + if (found_pos < 0) + /* The required string wasn't found. */ + return -1; + + if (!is_partial) { + /* Record where the required string matched. */ + state->req_pos = found_pos; + state->req_end = end_pos; + } + + if (pattern->req_offset >= 0) { + /* Step back from the required string to where we should start + * matching. + */ + found_pos += pattern->req_offset; + if (found_pos <= state->text_pos) + return found_pos; + } + break; + } + case RE_OP_STRING_IGN: + { + BOOL is_partial; + Py_ssize_t limit; + + if (search || pattern->req_offset < 0) + limit = state->slice_end; + else { + limit = state->slice_start + pattern->req_offset + + (Py_ssize_t)pattern->req_string->value_count; + if (limit > state->slice_end) + limit = state->slice_end; + } + + if (state->req_pos < 0 || state->text_pos > state->req_pos) + /* First time or already passed it. */ + found_pos = string_search_ign(state, pattern->req_string, + state->text_pos, limit, TRUE, &is_partial); + else { + found_pos = state->req_pos; + end_pos = state->req_end; + is_partial = FALSE; + } + + if (found_pos < 0) + /* The required string wasn't found. */ + return -1; + + if (!is_partial) { + /* Record where the required string matched. */ + state->req_pos = found_pos; + state->req_end = found_pos + + (Py_ssize_t)pattern->req_string->value_count; + } + + if (pattern->req_offset >= 0) { + /* Step back from the required string to where we should start + * matching. + */ + found_pos -= pattern->req_offset; + if (found_pos >= state->text_pos) + return found_pos; + } + break; + } + case RE_OP_STRING_IGN_REV: + { + BOOL is_partial; + Py_ssize_t limit; + + if (search || pattern->req_offset < 0) + limit = state->slice_start; + else { + limit = state->slice_end - pattern->req_offset - + (Py_ssize_t)pattern->req_string->value_count; + if (limit < state->slice_start) + limit = state->slice_start; + } + + if (state->req_pos < 0 || state->text_pos < state->req_pos) + /* First time or already passed it. */ + found_pos = string_search_ign_rev(state, pattern->req_string, + state->text_pos, limit, TRUE, &is_partial); + else { + found_pos = state->req_pos; + end_pos = state->req_end; + is_partial = FALSE; + } + + if (found_pos < 0) + /* The required string wasn't found. */ + return -1; + + if (!is_partial) { + /* Record where the required string matched. */ + state->req_pos = found_pos; + state->req_end = found_pos - + (Py_ssize_t)pattern->req_string->value_count; + } + + if (pattern->req_offset >= 0) { + /* Step back from the required string to where we should start + * matching. + */ + found_pos += pattern->req_offset; + if (found_pos <= state->text_pos) + return found_pos; + } + break; + } + case RE_OP_STRING_REV: + { + BOOL is_partial; + Py_ssize_t limit; + + if (search || pattern->req_offset < 0) + limit = state->slice_start; + else { + limit = state->slice_end - pattern->req_offset - + (Py_ssize_t)pattern->req_string->value_count; + if (limit < state->slice_start) + limit = state->slice_start; + } + + if (state->req_pos < 0 || state->text_pos < state->req_pos) + /* First time or already passed it. */ + found_pos = string_search_rev(state, pattern->req_string, + state->text_pos, limit, TRUE, &is_partial); + else { + found_pos = state->req_pos; + end_pos = state->req_end; + is_partial = FALSE; + } + + if (found_pos < 0) + /* The required string wasn't found. */ + return -1; + + if (!is_partial) { + /* Record where the required string matched. */ + state->req_pos = found_pos; + state->req_end = found_pos - + (Py_ssize_t)pattern->req_string->value_count; + } + + if (pattern->req_offset >= 0) { + /* Step back from the required string to where we should start + * matching. + */ + found_pos += pattern->req_offset; + if (found_pos <= state->text_pos) + return found_pos; + } + break; + } + } + + /* Start matching from the current position. */ + return state->text_pos; +} + +/* Tries to match a character pattern. */ +Py_LOCAL_INLINE(int) match_one(RE_State* state, RE_Node* node, Py_ssize_t + text_pos) { + switch (node->op) { + case RE_OP_ANY: + return try_match_ANY(state, node, text_pos); + case RE_OP_ANY_ALL: + return try_match_ANY_ALL(state, node, text_pos); + case RE_OP_ANY_ALL_REV: + return try_match_ANY_ALL_REV(state, node, text_pos); + case RE_OP_ANY_REV: + return try_match_ANY_REV(state, node, text_pos); + case RE_OP_ANY_U: + return try_match_ANY_U(state, node, text_pos); + case RE_OP_ANY_U_REV: + return try_match_ANY_U_REV(state, node, text_pos); + case RE_OP_CHARACTER: + return try_match_CHARACTER(state, node, text_pos); + case RE_OP_CHARACTER_IGN: + return try_match_CHARACTER_IGN(state, node, text_pos); + case RE_OP_CHARACTER_IGN_REV: + return try_match_CHARACTER_IGN_REV(state, node, text_pos); + case RE_OP_CHARACTER_REV: + return try_match_CHARACTER_REV(state, node, text_pos); + case RE_OP_PROPERTY: + return try_match_PROPERTY(state, node, text_pos); + case RE_OP_PROPERTY_IGN: + return try_match_PROPERTY_IGN(state, node, text_pos); + case RE_OP_PROPERTY_IGN_REV: + return try_match_PROPERTY_IGN_REV(state, node, text_pos); + case RE_OP_PROPERTY_REV: + return try_match_PROPERTY_REV(state, node, text_pos); + case RE_OP_RANGE: + return try_match_RANGE(state, node, text_pos); + case RE_OP_RANGE_IGN: + return try_match_RANGE_IGN(state, node, text_pos); + case RE_OP_RANGE_IGN_REV: + return try_match_RANGE_IGN_REV(state, node, text_pos); + case RE_OP_RANGE_REV: + return try_match_RANGE_REV(state, node, text_pos); + case RE_OP_SET_DIFF: + case RE_OP_SET_INTER: + case RE_OP_SET_SYM_DIFF: + case RE_OP_SET_UNION: + return try_match_SET(state, node, text_pos); + case RE_OP_SET_DIFF_IGN: + case RE_OP_SET_INTER_IGN: + case RE_OP_SET_SYM_DIFF_IGN: + case RE_OP_SET_UNION_IGN: + return try_match_SET_IGN(state, node, text_pos); + case RE_OP_SET_DIFF_IGN_REV: + case RE_OP_SET_INTER_IGN_REV: + case RE_OP_SET_SYM_DIFF_IGN_REV: + case RE_OP_SET_UNION_IGN_REV: + return try_match_SET_IGN_REV(state, node, text_pos); + case RE_OP_SET_DIFF_REV: + case RE_OP_SET_INTER_REV: + case RE_OP_SET_SYM_DIFF_REV: + case RE_OP_SET_UNION_REV: + return try_match_SET_REV(state, node, text_pos); + } + + return FALSE; +} + +/* Tests whether 2 nodes contains the same values. */ +Py_LOCAL_INLINE(BOOL) same_values(RE_Node* node_1, RE_Node* node_2) { + size_t i; + + if (node_1->value_count != node_2->value_count) + return FALSE; + + for (i = 0; i < node_1->value_count; i++) { + if (node_1->values[i] != node_2->values[i]) + return FALSE; + } + + return TRUE; +} + +/* Tests whether 2 nodes are equivalent (both string-like in the same way). */ +Py_LOCAL_INLINE(BOOL) equivalent_nodes(RE_Node* node_1, RE_Node* node_2) { + switch (node_1->op) { + case RE_OP_CHARACTER: + case RE_OP_STRING: + switch (node_2->op) { + case RE_OP_CHARACTER: + case RE_OP_STRING: + return same_values(node_1, node_2); + } + break; + case RE_OP_CHARACTER_IGN: + case RE_OP_STRING_IGN: + switch (node_2->op) { + case RE_OP_CHARACTER_IGN: + case RE_OP_STRING_IGN: + return same_values(node_1, node_2); + } + break; + case RE_OP_CHARACTER_IGN_REV: + case RE_OP_STRING_IGN_REV: + switch (node_2->op) { + case RE_OP_CHARACTER_IGN_REV: + case RE_OP_STRING_IGN_REV: + return same_values(node_1, node_2); + } + break; + case RE_OP_CHARACTER_REV: + case RE_OP_STRING_REV: + switch (node_2->op) { + case RE_OP_CHARACTER_REV: + case RE_OP_STRING_REV: + return same_values(node_1, node_2); + } + break; + } + + return FALSE; +} + +/* Saves the match as the best POSIX match (leftmost longest) found so far. */ +Py_LOCAL_INLINE(BOOL) save_best_match(RE_State* state) { + size_t group_count; + size_t g; + + state->best_match_pos = state->match_pos; + state->best_text_pos = state->text_pos; + state->found_match = TRUE; + + Py_MEMCPY(state->best_fuzzy_counts, state->fuzzy_counts, + sizeof(state->fuzzy_counts)); + + group_count = state->pattern->true_group_count; + if (group_count == 0) + return TRUE; + + if (!state->best_match_groups) { + /* Allocate storage for the groups of the best match. */ + state->best_match_groups = (RE_GroupData*)safe_alloc(state, group_count + * sizeof(RE_GroupData)); + if (!state->best_match_groups) + return FALSE; + + memset(state->best_match_groups, 0, group_count * + sizeof(RE_GroupData)); + + for (g = 0; g < group_count; g++) { + RE_GroupData* best; + RE_GroupData* group; + + best = &state->best_match_groups[g]; + group = &state->groups[g]; + + best->capacity = group->capacity; + best->captures = (RE_GroupSpan*)safe_alloc(state, best->capacity * + sizeof(RE_GroupSpan)); + if (!best->captures) + return FALSE; + } + } + + /* Copy the group spans and captures. */ + for (g = 0; g < group_count; g++) { + RE_GroupData* best; + RE_GroupData* group; + + best = &state->best_match_groups[g]; + group = &state->groups[g]; + + best->count = group->count; + best->current = group->current; + + if (best->count > best->capacity) { + RE_GroupSpan* new_captures; + + /* We need more space for the captures. */ + best->capacity = best->count; + new_captures = (RE_GroupSpan*)safe_realloc(state, best->captures, + best->capacity * sizeof(RE_GroupSpan)); + if (!new_captures) + return FALSE; + best->captures = new_captures; + } + + /* Copy the captures for this group. */ + Py_MEMCPY(best->captures, group->captures, group->count * + sizeof(RE_GroupSpan)); + } + + return TRUE; +} + +/* Restores the best match for a POSIX match (leftmost longest). */ +Py_LOCAL_INLINE(void) restore_best_match(RE_State* state) { + size_t group_count; + size_t g; + + if (!state->found_match) + return; + + state->match_pos = state->best_match_pos; + state->text_pos = state->best_text_pos; + + Py_MEMCPY(state->fuzzy_counts, state->best_fuzzy_counts, + sizeof(state->fuzzy_counts)); + + group_count = state->pattern->true_group_count; + if (group_count == 0) + return; + + /* Copy the group spans and captures. */ + for (g = 0; g < group_count; g++) { + RE_GroupData* group; + RE_GroupData* best; + + group = &state->groups[g]; + best = &state->best_match_groups[g]; + + group->count = best->count; + group->current = best->current; + + /* Copy the captures for this group. */ + Py_MEMCPY(group->captures, best->captures, best->count * + sizeof(RE_GroupSpan)); + } +} + +/* Checks whether the new match is better than the current match for a POSIX + * match (leftmost longest) and saves it if it is. + */ +Py_LOCAL_INLINE(BOOL) check_posix_match(RE_State* state) { + Py_ssize_t best_length; + Py_ssize_t new_length; + + if (!state->found_match) + return save_best_match(state); + + /* Check the overall match. */ + if (state->reverse) { + /* We're searching backwards. */ + best_length = state->match_pos - state->best_text_pos; + new_length = state->match_pos - state->text_pos; + } else { + /* We're searching forwards. */ + best_length = state->best_text_pos - state->match_pos; + new_length = state->text_pos - state->match_pos; + } + + if (new_length > best_length) + /* It's a longer match. */ + return save_best_match(state); + + return TRUE; +} + +/* Checks whether the current position is at the end of the text. */ +Py_LOCAL_INLINE(int) at_end(RE_State* state) { + return state->reverse ? state->text_pos == state->slice_start : + state->text_pos == state->slice_end; +} + +/* Checks whether 2 spans match. */ +Py_LOCAL_INLINE(BOOL) same_span(RE_GroupSpan span_1, RE_GroupSpan span_2) { + return span_1.start == span_2.start && span_1.end == span_2.end; +} + +/* Checks whether a span matches that of a group. */ +Py_LOCAL_INLINE(BOOL) same_span_as_group(RE_GroupData* group, RE_GroupSpan + span) { + return group->current >= 0 && same_span(group->captures[group->current], + span); +} + +/* Checks whether 2 groups have the same spam. */ +Py_LOCAL_INLINE(BOOL) same_span_of_group(RE_GroupData* group_1, RE_GroupData* + group_2) { + return (group_1->current >= 0 && group_2->current >= 0 && + same_span(group_1->captures[group_1->current], + group_2->captures[group_2->current])) || (group_1->current < 0 && + group_2->current < 0); +} + +/* Checks whether a string matches or at least partially if it's at the end. */ +Py_LOCAL_INLINE(BOOL) partial_string_match(RE_State* state, RE_Node* node, + Py_ssize_t text_pos) { + Py_ssize_t length; + RE_CODE* values; + Py_ssize_t ofs; + Py_UCS4 (*char_at)(void* text, Py_ssize_t pos); + + length = (Py_ssize_t)node->value_count; + values = node->values; + ofs = 0; + char_at = state->char_at; + + while (ofs < length) { + if (text_pos + ofs >= state->slice_end) + return TRUE; + + if (char_at(state->text, text_pos + ofs) != values[ofs]) + return FALSE; + + ++ofs; + } + + return TRUE; +} + +/* Checks whether a string matches or at least partially if it's at the end, + * ignoring case. + */ +Py_LOCAL_INLINE(BOOL) partial_string_match_ign(RE_State* state, RE_Node* node, + Py_ssize_t text_pos) { + Py_ssize_t length; + RE_CODE* values; + Py_ssize_t ofs; + Py_UCS4 (*char_at)(void* text, Py_ssize_t pos); + RE_EncodingTable* encoding; + RE_LocaleInfo* locale_info; + + length = (Py_ssize_t)node->value_count; + values = node->values; + ofs = 0; + char_at = state->char_at; + encoding = state->encoding; + locale_info = state->locale_info; + + while (ofs < length) { + if (text_pos + ofs >= state->slice_end) + return TRUE; + + if (!same_char_ign(encoding, locale_info, char_at(state->text, text_pos + + ofs), values[ofs])) + return FALSE; + + ++ofs; + } + + return TRUE; +} + +/* Performs a depth-first match or search from the context. */ +Py_LOCAL_INLINE(int) basic_match(RE_State* state, BOOL search) { + RE_EncodingTable* encoding; + RE_LocaleInfo* locale_info; + PatternObject* pattern; + RE_Node* start_node; + RE_NextNode start_pair; + Py_UCS4 (*char_at)(void* text, Py_ssize_t pos); + Py_ssize_t pattern_step; /* The overall step of the pattern (forwards or backwards). */ + Py_ssize_t string_pos; + BOOL do_search_start; + Py_ssize_t found_pos; + int status; + RE_Node* node; + int folded_pos; + int gfolded_pos; + TRACE(("<>\n")) + + encoding = state->encoding; + locale_info = state->locale_info; + pattern = state->pattern; + start_node = pattern->start_node; + + /* Look beyond any initial group node. */ + start_pair.node = start_node; + start_pair.test = pattern->start_test; + + /* Is the pattern anchored to the start or end of the string? */ + switch (start_pair.test->op) { + case RE_OP_END_OF_STRING: + if (state->reverse) { + /* Searching backwards. */ + if (state->text_pos != state->text_end) + return RE_ERROR_FAILURE; + + /* Don't bother to search further because it's anchored. */ + search = FALSE; + } + break; + case RE_OP_START_OF_STRING: + if (!state->reverse) { + /* Searching forwards. */ + if (state->text_pos != state->text_start) + return RE_ERROR_FAILURE; + + /* Don't bother to search further because it's anchored. */ + search = FALSE; + } + break; + } + + char_at = state->char_at; + pattern_step = state->reverse ? -1 : 1; + string_pos = -1; + do_search_start = pattern->do_search_start; + state->fewest_errors = state->max_errors; + + if (do_search_start && pattern->req_string && + equivalent_nodes(start_pair.test, pattern->req_string)) + do_search_start = FALSE; + +start_match: + if (state->iterations == 0 && safe_check_cancel(state)) + return RE_ERROR_CANCELLED; + + if (!push_uint8(state, &state->bstack, RE_OP_FAILURE)) + return RE_ERROR_MEMORY; + if (!push_bstack(state)) + return RE_ERROR_MEMORY; + + /* sstack: - + * + * bstack: FAILURE + * + * pstack: bstack + */ + + /* Clear the fuzzy counts. */ + if (state->is_fuzzy) + memset(state->fuzzy_counts, 0, sizeof(state->fuzzy_counts)); + + /* If we're searching, advance along the string until there could be a + * match. + */ + if (pattern->pattern_call_ref >= 0) { + RE_GuardList* guard_list; + + guard_list = &state->group_call_guard_list[pattern->pattern_call_ref]; + guard_list->count = 0; + guard_list->last_text_pos = -1; + } + + /* Locate the required string, if there's one, unless this is a recursive + * call of 'basic_match'. + */ + if (!pattern->req_string || state->text_pos < state->req_pos) + found_pos = state->text_pos; + else { + found_pos = locate_required_string(state, search); + if (found_pos < 0) + return RE_ERROR_FAILURE; + } + + if (search) { + state->text_pos = found_pos; + + if (do_search_start) { + RE_Position new_position; + +next_match_1: + /* 'search_start' will clear 'do_search_start' if it can't perform + * a fast search for the next possible match. This enables us to + * avoid the overhead of the call subsequently. + */ + status = search_start(state, &start_pair, &new_position, 0); + if (status == RE_ERROR_PARTIAL) { + state->match_pos = new_position.text_pos; + return status; + } else if (status != RE_ERROR_SUCCESS) + return status; + + node = new_position.node; + state->text_pos = new_position.text_pos; + + if (node->op == RE_OP_SUCCESS) { + /* Must the match advance past its start? */ + if (state->text_pos != state->search_anchor || + !state->must_advance) + return RE_ERROR_SUCCESS; + + state->text_pos = state->match_pos + pattern_step; + goto next_match_1; + } + + /* 'do_search_start' may have been cleared. */ + do_search_start = pattern->do_search_start; + } else { + /* Avoiding 'search_start', which we've found can't perform a fast + * search for the next possible match. + */ + node = start_node; + +next_match_2: + if (state->reverse) { + if (state->text_pos < state->slice_start) { + if (state->partial_side == RE_PARTIAL_LEFT) + return RE_ERROR_PARTIAL; + + return RE_ERROR_FAILURE; + } + } else { + if (state->text_pos > state->slice_end) { + if (state-> partial_side == RE_PARTIAL_RIGHT) + return RE_ERROR_PARTIAL; + + return RE_ERROR_FAILURE; + } + } + + state->match_pos = state->text_pos; + + if (node->op == RE_OP_SUCCESS) { + /* Must the match advance past its start? */ + if (state->text_pos != state->search_anchor || + !state->must_advance) { + BOOL success; + + if (state->match_all) { + /* We want to match all of the slice. */ + if (state->reverse) + success = state->text_pos == state->slice_start; + else + success = state->text_pos == state->slice_end; + } else + success = TRUE; + + if (success) + return RE_ERROR_SUCCESS; + } + + state->text_pos = state->match_pos + pattern_step; + goto next_match_2; + } + } + } else { + /* The start position is anchored to the current position. */ + if (found_pos != state->text_pos) + return RE_ERROR_FAILURE; + + node = start_node; + } + +advance: + /* The main matching loop. */ + for (;;) { + TRACE(("%" PY_FORMAT_SIZE_T "d|", state->text_pos)) + + /* Should we abort the matching? */ + state->iterations += 0x100U; + + if (state->iterations == 0 && safe_check_cancel(state)) + return RE_ERROR_CANCELLED; + + switch (node->op) { + case RE_OP_ANY: /* Any character except a newline. */ + TRACE(("%s\n", re_op_text[node->op])) + + status = try_match_ANY(state, node, state->text_pos); + if (status < 0) + return status; + + if (status == RE_ERROR_SUCCESS) { + ++state->text_pos; + node = node->next_1.node; + } else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_item(state, search, &node, 1); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + goto backtrack; + } else + goto backtrack; + break; + case RE_OP_ANY_ALL: /* Any character at all. */ + TRACE(("%s\n", re_op_text[node->op])) + + status = try_match_ANY_ALL(state, node, state->text_pos); + if (status < 0) + return status; + + if (status == RE_ERROR_SUCCESS) { + ++state->text_pos; + node = node->next_1.node; + } else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_item(state, search, &node, 1); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + goto backtrack; + } else + goto backtrack; + break; + case RE_OP_ANY_ALL_REV: /* Any character at all, backwards. */ + TRACE(("%s\n", re_op_text[node->op])) + + status = try_match_ANY_ALL_REV(state, node, state->text_pos); + if (status < 0) + return status; + + if (status == RE_ERROR_SUCCESS) { + --state->text_pos; + node = node->next_1.node; + } else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_item(state, search, &node, -1); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + goto backtrack; + } else + goto backtrack; + break; + case RE_OP_ANY_REV: /* Any character except a newline, backwards. */ + TRACE(("%s\n", re_op_text[node->op])) + + status = try_match_ANY_REV(state, node, state->text_pos); + if (status < 0) + return status; + + if (status == RE_ERROR_SUCCESS) { + --state->text_pos; + node = node->next_1.node; + } else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_item(state, search, &node, -1); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + goto backtrack; + } else + goto backtrack; + break; + case RE_OP_ANY_U: /* Any character except a line separator. */ + TRACE(("%s\n", re_op_text[node->op])) + + status = try_match_ANY_U(state, node, state->text_pos); + if (status < 0) + return status; + + if (status == RE_ERROR_SUCCESS) { + ++state->text_pos; + node = node->next_1.node; + } else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_item(state, search, &node, 1); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + goto backtrack; + } else + goto backtrack; + break; + case RE_OP_ANY_U_REV: /* Any character except a line separator, backwards. */ + TRACE(("%s\n", re_op_text[node->op])) + + status = try_match_ANY_U_REV(state, node, state->text_pos); + if (status < 0) + return status; + + if (status == RE_ERROR_SUCCESS) { + --state->text_pos; + node = node->next_1.node; + } else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_item(state, search, &node, -1); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + goto backtrack; + } else + goto backtrack; + break; + case RE_OP_ATOMIC: /* Start of an atomic group. */ + TRACE(("%s\n", re_op_text[node->op])) + + if (!push_captures(state, &state->bstack)) + return RE_ERROR_MEMORY; + if (!push_fuzzy_counts(state, &state->bstack, state->fuzzy_counts)) + return RE_ERROR_MEMORY; + if (!push_size(state, &state->bstack, state->capture_change)) + return RE_ERROR_MEMORY; + if (!push_sstack(state)) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, RE_OP_ATOMIC)) + return RE_ERROR_MEMORY; + if (!push_bstack(state)) + return RE_ERROR_MEMORY; + + /* bstack: captures fuzzy_counts capture_change sstack ATOMIC + * + * pstack: bstack + */ + + node = node->next_1.node; + break; + case RE_OP_BOUNDARY: /* At a word boundary. */ + TRACE(("%s %d\n", re_op_text[node->op], node->match)) + + status = try_match_BOUNDARY(state, node, state->text_pos); + if (status < 0) + return status; + + if (status == RE_ERROR_SUCCESS) + node = node->next_1.node; + else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_item(state, search, &node, 0); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + goto backtrack; + } else + goto backtrack; + break; + case RE_OP_BRANCH: /* 2-way branch. */ + { + RE_Position next_position; + TRACE(("%s\n", re_op_text[node->op])) + + status = try_match(state, &node->next_1, state->text_pos, + &next_position); + if (status < 0) + return status; + + if (status == RE_ERROR_SUCCESS) { + if (!push_ssize(state, &state->bstack, state->text_pos)) + return RE_ERROR_MEMORY; + if (!push_pointer(state, &state->bstack, + node->nonstring.next_2.node)) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, RE_OP_BRANCH)) + return RE_ERROR_MEMORY; + + /* bstack: text_pos node BRANCH */ + + node = next_position.node; + state->text_pos = next_position.text_pos; + } else + node = node->nonstring.next_2.node; + break; + } + case RE_OP_CALL_REF: /* A group call reference. */ + { + TRACE(("%s %d\n", re_op_text[node->op], node->values[0])) + + if (!push_pointer(state, &state->sstack, NULL)) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, RE_OP_CALL_REF)) + return RE_ERROR_MEMORY; + + /* sstack: NULL + * + * bstack: CALL_REF + */ + + node = node->next_1.node; + break; + } + case RE_OP_CHARACTER: /* A character. */ + TRACE(("%s %d %d\n", re_op_text[node->op], node->match, + node->values[0])) + + if (state->text_pos >= state->text_end && state->partial_side == + RE_PARTIAL_RIGHT) + return RE_ERROR_PARTIAL; + + if (state->text_pos < state->slice_end && + matches_CHARACTER(encoding, locale_info, node, + char_at(state->text, state->text_pos)) == node->match) { + state->text_pos += node->step; + node = node->next_1.node; + } else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_item(state, search, &node, 1); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + goto backtrack; + } else + goto backtrack; + break; + case RE_OP_CHARACTER_IGN: /* A character, ignoring case. */ + TRACE(("%s %d %d\n", re_op_text[node->op], node->match, + node->values[0])) + + if (state->text_pos >= state->text_end && state->partial_side == + RE_PARTIAL_RIGHT) + return RE_ERROR_PARTIAL; + + if (state->text_pos < state->slice_end && + matches_CHARACTER_IGN(encoding, locale_info, node, + char_at(state->text, state->text_pos)) == node->match) { + state->text_pos += node->step; + node = node->next_1.node; + } else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_item(state, search, &node, 1); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + goto backtrack; + } else + goto backtrack; + break; + case RE_OP_CHARACTER_IGN_REV: /* A character, backwards, ignoring case. */ + TRACE(("%s %d %d\n", re_op_text[node->op], node->match, + node->values[0])) + + if (state->text_pos <= state->text_start && state->partial_side == RE_PARTIAL_LEFT) + return RE_ERROR_PARTIAL; + + if (state->text_pos > state->slice_start && + matches_CHARACTER_IGN(encoding, locale_info, node, + char_at(state->text, state->text_pos - 1)) == node->match) { + state->text_pos += node->step; + node = node->next_1.node; + } else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_item(state, search, &node, -1); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + goto backtrack; + } else + goto backtrack; + break; + case RE_OP_CHARACTER_REV: /* A character, backwards. */ + TRACE(("%s %d %d\n", re_op_text[node->op], node->match, + node->values[0])) + + if (state->text_pos <= state->text_start && state->partial_side == RE_PARTIAL_LEFT) + return RE_ERROR_PARTIAL; + + if (state->text_pos > state->slice_start && + matches_CHARACTER(encoding, locale_info, node, + char_at(state->text, state->text_pos - 1)) == node->match) { + state->text_pos += node->step; + node = node->next_1.node; + } else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_item(state, search, &node, -1); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + goto backtrack; + } else + goto backtrack; + break; + case RE_OP_CONDITIONAL: /* Start of a conditional subpattern. */ + { + RE_LookaroundStateData data_l; + TRACE(("%s %d\n", re_op_text[node->op], node->match)) + + data_l.node = node; + data_l.slice_start = state->slice_start; + data_l.slice_end = state->slice_end; + data_l.text_pos = state->text_pos; + + if (!ByteStack_push_block(state, &state->sstack, (void*)&data_l, + sizeof(data_l))) + return RE_ERROR_MEMORY; + if (!push_captures(state, &state->bstack)) + return RE_ERROR_MEMORY; + if (!push_repeats(state, &state->bstack)) + return RE_ERROR_MEMORY; + if (!push_fuzzy_counts(state, &state->bstack, state->fuzzy_counts)) + return RE_ERROR_MEMORY; + if (!push_size(state, &state->bstack, state->capture_change)) + return RE_ERROR_MEMORY; + if (!push_sstack(state)) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, RE_OP_CONDITIONAL)) + return RE_ERROR_MEMORY; + if (!push_bstack(state)) + return RE_ERROR_MEMORY; + + /* sstack: node slice_start slice_end text_pos + * + * bstack: captures repeats fuzzy_counts capture_change sstack + * CONDITIONAL + * + * pstack: bstack + */ + + state->slice_start = state->text_start; + state->slice_end = state->text_end; + + node = node->next_1.node; + break; + } + case RE_OP_DEFAULT_BOUNDARY: /* At a default word boundary. */ + TRACE(("%s %d\n", re_op_text[node->op], node->match)) + + status = try_match_DEFAULT_BOUNDARY(state, node, state->text_pos); + if (status < 0) + return status; + + if (status == RE_ERROR_SUCCESS) + node = node->next_1.node; + else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_item(state, search, &node, 0); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + goto backtrack; + } else + goto backtrack; + break; + case RE_OP_DEFAULT_END_OF_WORD: /* At the default end of a word. */ + TRACE(("%s\n", re_op_text[node->op])) + + status = try_match_DEFAULT_END_OF_WORD(state, node, + state->text_pos); + if (status < 0) + return status; + + if (status == RE_ERROR_SUCCESS) + node = node->next_1.node; + else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_item(state, search, &node, 0); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + goto backtrack; + } else + goto backtrack; + break; + case RE_OP_DEFAULT_START_OF_WORD: /* At the default start of a word. */ + TRACE(("%s\n", re_op_text[node->op])) + + status = try_match_DEFAULT_START_OF_WORD(state, node, + state->text_pos); + if (status < 0) + return status; + + if (status == RE_ERROR_SUCCESS) + node = node->next_1.node; + else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_item(state, search, &node, 0); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + goto backtrack; + } else + goto backtrack; + break; + case RE_OP_END_ATOMIC: /* End of an atomic group. */ + TRACE(("%s\n", re_op_text[node->op])) + + /* sstack: ... + * + * bstack: captures fuzzy_counts capture_change sstack ATOMIC ... + * + * pstack: bstack + */ + + if (!pop_bstack(state)) + return RE_ERROR_MEMORY; + + /* sstack: ... + * + * bstack: captures fuzzy_counts capture_change sstack ATOMIC + * + * pstack: - + */ + + if (!drop_uint8(state, &state->bstack)) + return RE_ERROR_MEMORY; + if (!pop_sstack(state)) + return RE_ERROR_MEMORY; + + /* sstack: - + * + * bstack: captures fuzzy_counts capture_change + * + * pstack: - + */ + + if (!push_uint8(state, &state->bstack, RE_OP_END_ATOMIC)) + return RE_ERROR_MEMORY; + + /* bstack: captures fuzzy_counts capture_change END_ATOMIC + * + * pstack: - + */ + + node = node->next_1.node; + break; + case RE_OP_END_CONDITIONAL: /* End of a conditional subpattern. */ + { + RE_Node* conditional; + RE_LookaroundStateData data_l; + TRACE(("%s\n", re_op_text[node->op])) + + /* sstack: node slice_start slice_end text_pos ... + * + * bstack: captures repeats fuzzy_counts capture_change sstack + * CONDITIONAL ... + * + * pstack: bstack + */ + + if (!pop_bstack(state)) + return RE_ERROR_MEMORY; + + /* sstack: node slice_start slice_end text_pos ... + * + * bstack: captures repeats fuzzy_counts capture_change sstack + * CONDITIONAL + * + * pstack: - + */ + + if (!drop_uint8(state, &state->bstack)) + return RE_ERROR_MEMORY; + if (!pop_sstack(state)) + return RE_ERROR_MEMORY; + + /* sstack: node slice_start slice_end text_pos + * + * bstack: captures repeats fuzzy_counts capture_change + * + * pstack: - + */ + + if (!ByteStack_pop_block(state, &state->sstack, (void*)&data_l, + sizeof(data_l))) + return RE_ERROR_MEMORY; + + state->text_pos = data_l.text_pos; + state->slice_end = data_l.slice_end; + state->slice_start = data_l.slice_start; + conditional = data_l.node; + + /* sstack: - + * + * bstack: captures repeats fuzzy_counts capture_change + * + * pstack: - + */ + + if (conditional->match) { + /* It's a positive lookaround that's succeeded. */ + if (!push_uint8(state, &state->bstack, RE_OP_END_CONDITIONAL)) + return RE_ERROR_MEMORY; + + /* sstack: - + * + * bstack: captures repeats fuzzy_counts capture_change + * END_CONDITIONAL + * + * pstack: - + */ + + /* Go to the 'true' branch. */ + node = node->next_1.node; + } else { + /* It's a negative lookaround that's succeeded. */ + if (!pop_size(state, &state->bstack, &state->capture_change)) + return RE_ERROR_MEMORY; + if (!pop_fuzzy_counts(state, &state->bstack, + state->fuzzy_counts)) + return RE_ERROR_MEMORY; + if (!pop_repeats(state, &state->bstack)) + return RE_ERROR_MEMORY; + if (!pop_captures(state, &state->bstack)) + return RE_ERROR_MEMORY; + + /* sstack: - + * + * bstack: - + * + * pstack: - + */ + + /* Go to the 'false' branch. */ + node = conditional->nonstring.next_2.node; + } + break; + } + case RE_OP_END_FUZZY: /* End of fuzzy matching. */ + { + RE_Node* outer_node; + size_t outer_counts[RE_FUZZY_COUNT]; + size_t total_counts[RE_FUZZY_COUNT]; + TRACE(("%s\n", re_op_text[node->op])) + + /* sstack: outer_counts outer_node + * + * bstack: - + */ + + /* Are the inner constraints OK? */ + if (!fuzzy_within_constraints(state->fuzzy_counts, + state->fuzzy_node, state->max_errors)) + goto backtrack; + + if (!pop_pointer(state, &state->sstack, (void*)&outer_node)) + return RE_ERROR_MEMORY; + if (!pop_fuzzy_counts(state, &state->sstack, outer_counts)) + return RE_ERROR_MEMORY; + + /* sstack: - + * + * bstack: - + */ + + /* Add the inner counts to the outer counts. */ + total_counts[RE_FUZZY_SUB] = outer_counts[RE_FUZZY_SUB] + + state->fuzzy_counts[RE_FUZZY_SUB]; + total_counts[RE_FUZZY_INS] = outer_counts[RE_FUZZY_INS] + + state->fuzzy_counts[RE_FUZZY_INS]; + total_counts[RE_FUZZY_DEL] = outer_counts[RE_FUZZY_DEL] + + state->fuzzy_counts[RE_FUZZY_DEL]; + + /* Is the total number of errors OK? */ + state->total_errors = total_errors(total_counts); + + if (state->total_errors > state->max_errors) { + if (!push_fuzzy_counts(state, &state->sstack, outer_counts)) + return RE_ERROR_MEMORY; + if (!push_pointer(state, &state->sstack, outer_node)) + return RE_ERROR_MEMORY; + + /* sstack: outer_counts outer_node + * + * bstack: - + */ + goto backtrack; + } + + /* Save the inner fuzzy info. */ + if (!push_fuzzy_counts(state, &state->bstack, state->fuzzy_counts)) + return RE_ERROR_MEMORY; + if (!push_ssize(state, &state->bstack, 0)) + return RE_ERROR_MEMORY; + if (!push_pointer(state, &state->bstack, state->fuzzy_node)) + return RE_ERROR_MEMORY; + if (!push_ssize(state, &state->bstack, state->text_pos)) + return RE_ERROR_MEMORY; + if (!push_pointer(state, &state->bstack, node)) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, RE_OP_END_FUZZY)) + return RE_ERROR_MEMORY; + + Py_MEMCPY(state->fuzzy_counts, total_counts, sizeof(total_counts)); + state->fuzzy_node = outer_node; + + /* sstack: - + * + * bstack: inner_counts inner_node text_pos end_fuzzy_node + * END_FUZZY + */ + + node = node->next_1.node; + break; + } + case RE_OP_END_GREEDY_REPEAT: /* End of a greedy repeat. */ + { + RE_CODE index; + RE_RepeatData* rp_data; + BOOL changed; + BOOL try_body; + int body_status; + RE_Position next_body_position; + BOOL try_tail; + int tail_status; + RE_Position next_tail_position; + RE_BodyEndStateData data_be; + TRACE(("%s %d\n", re_op_text[node->op], node->values[0])) + + /* Repeat indexes are 0-based. */ + index = node->values[0]; + rp_data = &state->repeats[index]; + + /* The body has matched successfully at this position. */ + if (!guard_repeat(state, index, rp_data->start, RE_STATUS_BODY, + FALSE)) + return RE_ERROR_MEMORY; + + ++rp_data->count; + + /* Have we advanced through the text or has a capture group change? + */ + changed = rp_data->capture_change != state->capture_change || + state->text_pos != rp_data->start; + + /* Additional checks are needed if there's fuzzy matching. */ + if (changed && state->is_fuzzy && rp_data->count >= + node->values[1]) + changed = !(node->step == 1 ? state->text_pos >= + state->slice_end : state->text_pos <= state->slice_start); + + /* The counts are of type size_t, so the format needs to specify + * that. + */ + TRACE((" min is %u, max is %u, count is %" PY_FORMAT_SIZE_T "u\n", + node->values[1], node->values[2], rp_data->count)) + + /* Could the body or tail match? */ + try_body = changed && (rp_data->count < node->values[2] || + ~node->values[2] == 0) && !is_repeat_guarded(state, index, + state->text_pos, RE_STATUS_BODY); + if (try_body) { + body_status = try_match(state, &node->next_1, state->text_pos, + &next_body_position); + if (body_status < 0) { + if (body_status == RE_ERROR_PARTIAL && rp_data->count >= + node->values[1] && at_end(state)) + body_status = RE_ERROR_FAILURE; + else + return body_status; + } + + if (body_status == RE_ERROR_FAILURE) + try_body = FALSE; + } else + body_status = RE_ERROR_FAILURE; + + try_tail = (!changed || rp_data->count >= node->values[1]) && + !is_repeat_guarded(state, index, state->text_pos, + RE_STATUS_TAIL); + if (try_tail) { + tail_status = try_match(state, &node->nonstring.next_2, + state->text_pos, &next_tail_position); + if (tail_status < 0) + return tail_status; + + if (tail_status == RE_ERROR_FAILURE) + try_tail = FALSE; + } else + tail_status = RE_ERROR_FAILURE; + + if (!try_body && !try_tail) { + /* Neither the body nor the tail could match. */ + --rp_data->count; + goto backtrack; + } + + if (body_status < 0 || (body_status == 0 && tail_status < 0)) + return RE_ERROR_PARTIAL; + + /* Record info in case we backtrack into the body. */ + data_be.count = rp_data->count - 1; + data_be.start = rp_data->start; + data_be.capture_change = rp_data->capture_change; + data_be.index = index; + + if (!ByteStack_push_block(state, &state->bstack, (void*)&data_be, + sizeof(data_be))) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, RE_OP_BODY_END)) + return RE_ERROR_MEMORY; + + /* bstack: count start capture_change index BODY_END */ + + if (try_body) { + if (try_tail) { + /* Both the body and the tail could match, but the body + * takes precedence. If the body fails to match then we + * want to try the tail before backtracking further. + */ + RE_MatchBodyTailStateData data_mbt; + + /* Record backtracking info for matching the tail. */ + data_mbt.position = next_tail_position; + data_mbt.count = rp_data->count; + data_mbt.start = state->text_pos; + data_mbt.capture_change = state->capture_change; + data_mbt.index = index; + data_mbt.text_pos = state->text_pos; + + if (!ByteStack_push_block(state, &state->bstack, + (void*)&data_mbt, sizeof(data_mbt))) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, RE_OP_MATCH_TAIL)) + return RE_ERROR_MEMORY; + + /* bstack: position count start capture_change index + * text_pos MATCH_TAIL + */ + } + + /* Record backtracking info in case the body fails to match. */ + if (!push_code(state, &state->bstack, index)) + return RE_ERROR_MEMORY; + if (!push_ssize(state, &state->bstack, state->text_pos)) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, RE_OP_BODY_START)) + return RE_ERROR_MEMORY; + + /* bstack: index text_pos BODY_START */ + + rp_data->capture_change = state->capture_change; + rp_data->start = state->text_pos; + + /* Advance into the body. */ + node = next_body_position.node; + state->text_pos = next_body_position.text_pos; + } else { + /* Only the tail could match. */ + + /* Record backtracking info in case the tail fails to match. */ + if (!push_code(state, &state->bstack, index)) + return RE_ERROR_MEMORY; + if (!push_ssize(state, &state->bstack, state->text_pos)) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, RE_OP_TAIL_START)) + return RE_ERROR_MEMORY; + + /* bstack: index text_pos TAIL_START */ + + /* Advance into the tail. */ + node = next_tail_position.node; + state->text_pos = next_tail_position.text_pos; + } + break; + } + case RE_OP_END_GROUP: /* End of a capture group. */ + { + RE_CODE private_index; + RE_CODE public_index; + RE_GroupData* group; + BOOL capture; + TRACE(("%s %d\n", re_op_text[node->op], node->values[1])) + + /* Capture group indexes are 1-based (excluding group 0, which is + * the entire matched string). + */ + private_index = node->values[0]; + public_index = node->values[1]; + group = &state->groups[private_index - 1]; + capture = (BOOL)node->values[2]; + + if (capture) { + RE_GroupSpan span; + RE_GroupStateData data_g; + + /* sstack: start + * + * bstack: - + */ + + if (!pop_ssize(state, &state->sstack, &span.start)) + return RE_ERROR_MEMORY; + + span.end = state->text_pos; + + data_g.text_pos = span.start; + data_g.current = group->current; + data_g.capture_change = state->capture_change; + data_g.private_index = private_index; + data_g.public_index = public_index; + + if (!ByteStack_push_block(state, &state->bstack, + (void*)&data_g, sizeof(data_g))) + return RE_ERROR_MEMORY; + + if (pattern->group_info[private_index - 1].referenced && + !same_span_as_group(group, span)) + ++state->capture_change; + + if (!save_capture(state, private_index, public_index, span)) + return RE_ERROR_MEMORY; + group->current = (Py_ssize_t)group->count - 1; + } else { + if (!push_ssize(state, &state->sstack, state->text_pos)) + return RE_ERROR_MEMORY; + } + + if (!push_bool(state, &state->bstack, capture)) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, RE_OP_END_GROUP)) + return RE_ERROR_MEMORY; + + /* If capturing: + * + * sstack: - + * + * bstack: start current capture_change private_index public_index + * TRUE END_GROUP + * + * else: + * + * sstack: end + * + * bstack: FALSE END_GROUP + */ + + node = node->next_1.node; + break; + } + case RE_OP_END_LAZY_REPEAT: /* End of a lazy repeat. */ + { + RE_CODE index; + RE_RepeatData* rp_data; + BOOL changed; + BOOL try_body; + int body_status; + RE_Position next_body_position; + BOOL try_tail; + int tail_status; + RE_Position next_tail_position; + RE_BodyEndStateData data_be; + TRACE(("%s %d\n", re_op_text[node->op], node->values[0])) + + /* Repeat indexes are 0-based. */ + index = node->values[0]; + rp_data = &state->repeats[index]; + + /* The body has matched successfully at this position. */ + if (!guard_repeat(state, index, rp_data->start, RE_STATUS_BODY, + FALSE)) + return RE_ERROR_MEMORY; + + ++rp_data->count; + + /* Have we advanced through the text or has a capture group change? + */ + changed = rp_data->capture_change != state->capture_change || + state->text_pos != rp_data->start; + + /* Additional checks are needed if there's fuzzy matching. */ + if (changed && state->is_fuzzy && rp_data->count >= + node->values[1]) + changed = !(node->step == 1 ? state->text_pos >= + state->slice_end : state->text_pos <= state->slice_start); + + /* The counts are of type size_t, so the format needs to specify + * that. + */ + TRACE((" min is %u, max is %u, count is %" PY_FORMAT_SIZE_T "u\n", + node->values[1], node->values[2], rp_data->count)) + + /* Could the body or tail match? */ + try_body = changed && (rp_data->count < node->values[2] || + ~node->values[2] == 0) && !is_repeat_guarded(state, index, + state->text_pos, RE_STATUS_BODY); + if (try_body) { + body_status = try_match(state, &node->next_1, state->text_pos, + &next_body_position); + if (body_status < 0) + return body_status; + + if (body_status == RE_ERROR_FAILURE) + try_body = FALSE; + } else + body_status = RE_ERROR_FAILURE; + + try_tail = (!changed || rp_data->count >= node->values[1]) && + !is_repeat_guarded(state, index, state->text_pos, + RE_STATUS_TAIL); + if (try_tail) { + tail_status = try_match(state, &node->nonstring.next_2, + state->text_pos, &next_tail_position); + if (tail_status < 0) + return tail_status; + + if (tail_status == RE_ERROR_FAILURE) + try_tail = FALSE; + } else + tail_status = RE_ERROR_FAILURE; + + if (!try_body && !try_tail) { + /* Neither the body nor the tail could match. */ + --rp_data->count; + goto backtrack; + } + + if (body_status < 0 || (body_status == 0 && tail_status < 0)) + return RE_ERROR_PARTIAL; + + /* Record info in case we backtrack into the body. */ + data_be.count = rp_data->count - 1; + data_be.start = rp_data->start; + data_be.capture_change = rp_data->capture_change; + data_be.index = index; + + if (!ByteStack_push_block(state, &state->bstack, (void*)&data_be, + sizeof(data_be))) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, RE_OP_BODY_END)) + return RE_ERROR_MEMORY; + + /* bstack: count start capture_change index BODY_END */ + + if (try_tail) { + if (try_body) { + /* Both the body and the tail could match, but The tail + * takes precedence. If the tail fails to match then we + * want to try the body before backtracking further. + */ + RE_MatchBodyTailStateData data_mbt; + + /* Record backtracking info for matching the body. */ + data_mbt.position = next_body_position; + data_mbt.count = rp_data->count; + data_mbt.start = state->text_pos; + data_mbt.capture_change = state->capture_change; + data_mbt.index = index; + data_mbt.text_pos = state->text_pos; + + if (!ByteStack_push_block(state, &state->bstack, + (void*)&data_mbt, sizeof(data_mbt))) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, RE_OP_MATCH_BODY)) + return RE_ERROR_MEMORY; + + /* bstack: position count start capture_change index + * text_pos MATCH_BODY + */ + } + + /* Record backtracking info in case the tail fails to match. */ + if (!push_code(state, &state->bstack, index)) + return RE_ERROR_MEMORY; + if (!push_ssize(state, &state->bstack, state->text_pos)) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, RE_OP_TAIL_START)) + return RE_ERROR_MEMORY; + + /* bstack: index text_pos TAIL_START */ + + /* Advance into the tail. */ + node = next_tail_position.node; + state->text_pos = next_tail_position.text_pos; + } else { + /* Only the body could match. */ + + /* Record backtracking info in case the body fails to + * match. + */ + if (!push_code(state, &state->bstack, index)) + return RE_ERROR_MEMORY; + if (!push_ssize(state, &state->bstack, state->text_pos)) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, RE_OP_BODY_START)) + return RE_ERROR_MEMORY; + + /* bstack: index text_pos BODY_START */ + + rp_data->capture_change = state->capture_change; + rp_data->start = state->text_pos; + + /* Advance into the body. */ + node = next_body_position.node; + state->text_pos = next_body_position.text_pos; + } + break; + } + case RE_OP_END_LOOKAROUND: /* End of a lookaround subpattern. */ + { + RE_LookaroundStateData data_l; + RE_Node* lookaround; + TRACE(("%s\n", re_op_text[node->op])) + + /* sstack: node slice_start slice_end text_pos ... + * + * bstack: [captures TRUE | FALSE] fuzzy_counts capture_change + * sstack LOOKAROUND ... + * + * pstack: bstack + */ + + if (!pop_bstack(state)) + return RE_ERROR_MEMORY; + + /* sstack: node slice_start slice_end text_pos ... + * + * bstack: [captures TRUE | FALSE] fuzzy_counts capture_change + * sstack LOOKAROUND + * + * pstack: - + */ + + if (!drop_uint8(state, &state->bstack)) + return RE_ERROR_MEMORY; + if (!pop_sstack(state)) + return RE_ERROR_MEMORY; + + /* sstack: node slice_start slice_end text_pos + * + * bstack: [captures TRUE | FALSE] fuzzy_counts capture_change + * + * pstack: - + */ + + if (!ByteStack_pop_block(state, &state->sstack, (void*)&data_l, + sizeof(data_l))) + return RE_ERROR_MEMORY; + + state->text_pos = data_l.text_pos; + state->slice_end = data_l.slice_end; + state->slice_start = data_l.slice_start; + lookaround = data_l.node; + + /* sstack: - + * + * bstack: [captures TRUE | FALSE] fuzzy_counts capture_change + * + * pstack: - + */ + + if (lookaround->match) { + /* It's a positive lookaround that's succeeded. */ + if (!push_uint8(state, &state->bstack, RE_OP_END_LOOKAROUND)) + return RE_ERROR_MEMORY; + + /* sstack: - + * + * bstack: [captures TRUE | FALSE] fuzzy_counts capture_change + * END_LOOKAROUND + * + * pstack: - + */ + + /* Go to the 'true' branch. */ + node = node->next_1.node; + } else { + BOOL has_groups; + + /* It's a negative lookaround that's succeeded. */ + if (!pop_size(state, &state->bstack, &state->capture_change)) + return RE_ERROR_MEMORY; + if (!pop_fuzzy_counts(state, &state->bstack, + state->fuzzy_counts)) + return RE_ERROR_MEMORY; + if (!pop_bool(state, &state->bstack, &has_groups)) + return RE_ERROR_MEMORY; + if (has_groups) { + if (!pop_captures(state, &state->bstack)) + return RE_ERROR_MEMORY; + } + + /* sstack: - + * + * bstack: - + * + * pstack: - + */ + + /* Go to the 'false' branch. */ + goto backtrack; + } + break; + } + case RE_OP_END_OF_LINE: /* At the end of a line. */ + TRACE(("%s\n", re_op_text[node->op])) + + status = try_match_END_OF_LINE(state, node, state->text_pos); + if (status < 0) + return status; + + if (status == RE_ERROR_SUCCESS) + node = node->next_1.node; + else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_item(state, search, &node, 0); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + goto backtrack; + } else + goto backtrack; + break; + case RE_OP_END_OF_LINE_U: /* At the end of a line. */ + TRACE(("%s\n", re_op_text[node->op])) + + status = try_match_END_OF_LINE_U(state, node, state->text_pos); + if (status < 0) + return status; + + if (status == RE_ERROR_SUCCESS) + node = node->next_1.node; + else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_item(state, search, &node, 0); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + goto backtrack; + } else + goto backtrack; + break; + case RE_OP_END_OF_STRING: /* At the end of the string. */ + TRACE(("%s\n", re_op_text[node->op])) + + status = try_match_END_OF_STRING(state, node, state->text_pos); + if (status < 0) + return status; + + if (status == RE_ERROR_SUCCESS) + node = node->next_1.node; + else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_item(state, search, &node, 0); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + goto backtrack; + } else + goto backtrack; + break; + case RE_OP_END_OF_STRING_LINE: /* At the end of string or final newline. */ + TRACE(("%s\n", re_op_text[node->op])) + + status = try_match_END_OF_STRING_LINE(state, node, + state->text_pos); + if (status < 0) + return status; + + if (status == RE_ERROR_SUCCESS) + node = node->next_1.node; + else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_item(state, search, &node, 0); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + goto backtrack; + } else + goto backtrack; + break; + case RE_OP_END_OF_STRING_LINE_U: /* At the end of string or final newline. */ + TRACE(("%s\n", re_op_text[node->op])) + + status = try_match_END_OF_STRING_LINE_U(state, node, + state->text_pos); + if (status < 0) + return status; + + if (status == RE_ERROR_SUCCESS) + node = node->next_1.node; + else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_item(state, search, &node, 0); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + goto backtrack; + } else + goto backtrack; + break; + case RE_OP_END_OF_WORD: /* At the end of a word. */ + TRACE(("%s\n", re_op_text[node->op])) + + status = try_match_END_OF_WORD(state, node, state->text_pos); + if (status < 0) + return status; + + if (status == RE_ERROR_SUCCESS) + node = node->next_1.node; + else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_item(state, search, &node, 0); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + goto backtrack; + } else + goto backtrack; + break; + case RE_OP_FAILURE: /* Failure. */ + goto backtrack; + case RE_OP_FUZZY: /* Fuzzy matching. */ + { + TRACE(("%s\n", re_op_text[node->op])) + + /* Save the outer fuzzy info. */ + if (!push_fuzzy_counts(state, &state->sstack, state->fuzzy_counts)) + return RE_ERROR_MEMORY; + if (!push_pointer(state, &state->sstack, state->fuzzy_node)) + return RE_ERROR_MEMORY; + + /* Initialise the inner fuzzy info. */ + memset(state->fuzzy_counts, 0, sizeof(state->fuzzy_counts)); + state->fuzzy_node = node; + + if (!push_uint8(state, &state->bstack, RE_OP_FUZZY)) + return RE_ERROR_MEMORY; + + /* sstack: outer_counts outer_node + * + * bstack: FUZZY + */ + + node = node->next_1.node; + break; + } + case RE_OP_GRAPHEME_BOUNDARY: /* At a grapheme boundary. */ + TRACE(("%s\n", re_op_text[node->op])) + + status = try_match_GRAPHEME_BOUNDARY(state, node, state->text_pos); + if (status < 0) + return status; + + if (status == RE_ERROR_SUCCESS) + node = node->next_1.node; + else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_item(state, search, &node, 0); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + goto backtrack; + } else + goto backtrack; + break; + case RE_OP_GREEDY_REPEAT: /* Greedy repeat. */ + { + RE_CODE index; + RE_RepeatData* rp_data; + BOOL try_body; + int body_status; + RE_Position next_body_position; + BOOL try_tail; + int tail_status; + RE_Position next_tail_position; + RE_RepeatStateData data_r; + TRACE(("%s %d\n", re_op_text[node->op], node->values[0])) + + /* Repeat indexes are 0-based. */ + index = node->values[0]; + rp_data = &state->repeats[index]; + + /* We might need to backtrack into the head, so save the current + * repeat. + */ + data_r.count = rp_data->count; + data_r.start = rp_data->start; + data_r.capture_change = rp_data->capture_change; + data_r.index = index; + data_r.text_pos = state->text_pos; + + if (!ByteStack_push_block(state, &state->bstack, (void*)&data_r, + sizeof(data_r))) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, RE_OP_GREEDY_REPEAT)) + return RE_ERROR_MEMORY; + + /* bstack: count start capture_change index text_pos GREEDY_REPEAT + */ + + /* Initialise the new repeat. */ + rp_data->count = 0; + rp_data->start = state->text_pos; + rp_data->capture_change = state->capture_change; + + /* Could the body or tail match? */ +#if defined(VERBOSE) + printf(" is_repeat_guarded(..., RE_STATUS_BODY) returns %d\n", + is_repeat_guarded(state, index, state->text_pos, + RE_STATUS_BODY)); +#endif + try_body = node->values[2] > 0 && !is_repeat_guarded(state, index, + state->text_pos, RE_STATUS_BODY); + if (try_body) { + body_status = try_match(state, &node->next_1, state->text_pos, + &next_body_position); + if (body_status < 0) + return body_status; + + if (body_status == RE_ERROR_FAILURE) + try_body = FALSE; + } else + body_status = RE_ERROR_FAILURE; + + try_tail = node->values[1] == 0; + if (try_tail) { + tail_status = try_match(state, &node->nonstring.next_2, + state->text_pos, &next_tail_position); + if (tail_status < 0) + return tail_status; + + if (tail_status == RE_ERROR_FAILURE) + try_tail = FALSE; + } else + tail_status = RE_ERROR_FAILURE; + + if (!try_body && !try_tail) + /* Neither the body nor the tail could match. */ + goto backtrack; + + if (body_status < 0 || (body_status == 0 && tail_status < 0)) + return RE_ERROR_PARTIAL; + + if (try_body) { + if (try_tail) { + /* Both the body and the tail could match, but the body + * takes precedence. If the body fails to match then we + * want to try the tail before backtracking further. + */ + RE_MatchBodyTailStateData data_mbt; + + /* Record backtracking info for matching the tail. */ + data_mbt.position = next_tail_position; + data_mbt.count = rp_data->count; + data_mbt.start = rp_data->start; + data_mbt.capture_change = rp_data->capture_change; + data_mbt.index = index; + data_mbt.text_pos = state->text_pos; + + if (!ByteStack_push_block(state, &state->bstack, + (void*)&data_mbt, sizeof(data_mbt))) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, RE_OP_MATCH_TAIL)) + return RE_ERROR_MEMORY; + + /* bstack: position count start capture_change index + * text_pos MATCH_TAIL + */ + } + + /* Record backtracking info in case the body fails to match. */ + if (!push_code(state, &state->bstack, index)) + return RE_ERROR_MEMORY; + if (!push_ssize(state, &state->bstack, state->text_pos)) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, RE_OP_BODY_START)) + return RE_ERROR_MEMORY; + + /* bstack: index text_pos BODY_START */ + + /* Advance into the body. */ + node = next_body_position.node; + state->text_pos = next_body_position.text_pos; + } else { + /* Only the tail could match. */ + + /* Record backtracking info in case the tail fails to match. */ + if (!push_code(state, &state->bstack, index)) + return RE_ERROR_MEMORY; + if (!push_ssize(state, &state->bstack, state->text_pos)) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, RE_OP_TAIL_START)) + return RE_ERROR_MEMORY; + + /* bstack: index text_pos TAIL_START */ + + /* Advance into the tail. */ + node = next_tail_position.node; + state->text_pos = next_tail_position.text_pos; + } + break; + } + case RE_OP_GREEDY_REPEAT_ONE: /* Greedy repeat for one character. */ + { + RE_CODE index; + RE_RepeatData* rp_data; + size_t count; + BOOL is_partial; + BOOL match; + TRACE(("%s %d\n", re_op_text[node->op], node->values[0])) + + /* Repeat indexes are 0-based. */ + index = node->values[0]; + rp_data = &state->repeats[index]; + + if (is_repeat_guarded(state, index, state->text_pos, + RE_STATUS_BODY)) + goto backtrack; + + /* Count how many times the character repeats, up to the maximum. + */ + count = count_one(state, node->nonstring.next_2.node, + state->text_pos, node->values[2], &is_partial); + if (is_partial) { + state->text_pos += (Py_ssize_t)count * node->step; + return RE_ERROR_PARTIAL; + } + + /* Unmatch until it's not guarded. */ + match = FALSE; + for (;;) { + if (count < node->values[1]) + /* The number of repeats is below the minimum. */ + break; + + if (!is_repeat_guarded(state, index, state->text_pos + + (Py_ssize_t)count * node->step, RE_STATUS_TAIL)) { + /* It's not guarded at this position. */ + match = TRUE; + break; + } + + if (count == 0) + break; + + --count; + } + + if (!match) { + /* The repeat has failed to match at this position. */ + if (!guard_repeat(state, index, state->text_pos, + RE_STATUS_BODY, TRUE)) + return RE_ERROR_MEMORY; + goto backtrack; + } + + if (count > node->values[1]) { + /* Record the backtracking info. */ + RE_RepeatOneStateData data_ro; + + data_ro.count = rp_data->count; + data_ro.start = rp_data->start; + data_ro.node = node; + data_ro.index = index; + + if (!ByteStack_push_block(state, &state->bstack, + (void*)&data_ro, sizeof(data_ro))) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, + RE_OP_GREEDY_REPEAT_ONE)) + return RE_ERROR_MEMORY; + + /* bstack: count start node index GREEDY_REPEAT_ONE */ + + rp_data->start = state->text_pos; + rp_data->count = count; + } + + /* Advance into the tail. */ + state->text_pos += (Py_ssize_t)count * node->step; + node = node->next_1.node; + break; + } + case RE_OP_GROUP_CALL: /* Group call. */ + { + size_t index; + RE_Node* next_node; + size_t r; + TRACE(("%s %d\n", re_op_text[node->op], node->values[0])) + + index = node->values[0]; + next_node = node->next_1.node; + + /* For the caller. */ + if (!push_groups(state, &state->sstack)) + return RE_ERROR_MEMORY; + if (!push_repeats(state, &state->sstack)) + return RE_ERROR_MEMORY; + if (!push_size(state, &state->sstack, state->capture_change)) + return RE_ERROR_MEMORY; + if (!push_pointer(state, &state->sstack, next_node)) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, RE_OP_GROUP_CALL)) + return RE_ERROR_MEMORY; + + /* sstack: caller_groups caller_repeats capture_change return_node + * + * bstack: GROUP_CALL + */ + + /* Clear the repeat guards for the group call. They'll be restored + * on return. + */ + for (r = 0; r < state->pattern->repeat_count; r++) { + RE_RepeatData* repeat; + + repeat = &state->repeats[r]; + repeat->body_guard_list.count = 0; + repeat->body_guard_list.last_text_pos = -1; + repeat->tail_guard_list.count = 0; + repeat->tail_guard_list.last_text_pos = -1; + } + + /* Call a group, skipping its CALL_REF node. */ + node = pattern->call_ref_info[index].node->next_1.node; + break; + } + case RE_OP_GROUP_EXISTS: /* Capture group exists. */ + { + RE_CODE index; + TRACE(("%s %d\n", re_op_text[node->op], node->values[0])) + + /* Capture group indexes are 1-based (excluding group 0, which is + * the entire matched string). + * + * Check whether the captured text, if any, exists at this position + * in the string. + * + * A group index of 0, however, means that it's a DEFINE, which we + * should skip. + */ + index = node->values[0]; + + if (index == 0) + /* Skip past the body. */ + node = node->nonstring.next_2.node; + else { + RE_GroupData* group; + + group = &state->groups[index - 1]; + if (group->current >= 0) + /* The 'true' branch. */ + node = node->next_1.node; + else + /* The 'false' branch. */ + node = node->nonstring.next_2.node; + } + break; + } + case RE_OP_GROUP_RETURN: /* Group return. */ + { + RE_Node* return_node; + TRACE(("%s\n", re_op_text[node->op])) + + /* If called: + * + * sstack: caller_groups caller_repeats capture_change return_node + * + * bstack: - + * + * else: + * + * sstack: NULL + * + * bstack: - + */ + + if (!pop_pointer(state, &state->sstack, (void*)&return_node)) + return RE_ERROR_MEMORY; + + if (return_node) { + /* The group was called. */ + node = return_node; + + /* For the callee. */ + if (!push_groups(state, &state->bstack)) + return RE_ERROR_MEMORY; + if (!push_repeats(state, &state->bstack)) + return RE_ERROR_MEMORY; + if (!push_size(state, &state->bstack, state->capture_change)) + return RE_ERROR_MEMORY; + if (!push_pointer(state, &state->bstack, return_node)) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, RE_OP_GROUP_RETURN)) + return RE_ERROR_MEMORY; + + /* For the caller. */ + if (!pop_size(state, &state->sstack, &state->capture_change)) + return RE_ERROR_MEMORY; + if (!pop_repeats(state, &state->sstack)) + return RE_ERROR_MEMORY; + if (!pop_groups(state, &state->sstack)) + return RE_ERROR_MEMORY; + } else { + /* The group was not called. */ + if (!push_pointer(state, &state->bstack, NULL)) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, RE_OP_GROUP_RETURN)) + return RE_ERROR_MEMORY; + + node = node->next_1.node; + } + + /* If called: + * + * sstack: - + * + * bstack: callee_groups callee_repeats capture_change return_node + * GROUP_RETURN + * + * else: + * + * sstack: - + * + * bstack: NULL GROUP_RETURN + */ + break; + } + case RE_OP_KEEP: /* Keep. */ + TRACE(("%s\n", re_op_text[node->op])) + + if (!push_ssize(state, &state->bstack, state->match_pos)) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, RE_OP_KEEP)) + return RE_ERROR_MEMORY; + + /* bstack: match_pos KEEP */ + + state->match_pos = state->text_pos; + + node = node->next_1.node; + break; + case RE_OP_LAZY_REPEAT: /* Lazy repeat. */ + { + RE_CODE index; + RE_RepeatData* rp_data; + BOOL try_body; + int body_status; + RE_Position next_body_position; + BOOL try_tail; + int tail_status; + RE_Position next_tail_position; + RE_RepeatStateData data_r; + TRACE(("%s %d\n", re_op_text[node->op], node->values[0])) + + /* Repeat indexes are 0-based. */ + index = node->values[0]; + rp_data = &state->repeats[index]; + + /* We might need to backtrack into the head, so save the current + * repeat. + */ + data_r.count = rp_data->count; + data_r.start = rp_data->start; + data_r.capture_change = rp_data->capture_change; + data_r.index = index; + data_r.text_pos = state->text_pos; + + if (!ByteStack_push_block(state, &state->bstack, (void*)&data_r, + sizeof(data_r))) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, RE_OP_LAZY_REPEAT)) + return RE_ERROR_MEMORY; + + /* bstack: count start capture_change index text_pos LAZY_REPEAT */ + + /* Initialise the new repeat. */ + rp_data->count = 0; + rp_data->start = state->text_pos; + rp_data->capture_change = state->capture_change; + + /* Could the body or tail match? */ +#if defined(VERBOSE) + printf(" is_repeat_guarded(..., RE_STATUS_BODY) returns %d\n", + is_repeat_guarded(state, index, state->text_pos, + RE_STATUS_BODY)); +#endif + try_body = node->values[2] > 0 && !is_repeat_guarded(state, index, + state->text_pos, RE_STATUS_BODY); + if (try_body) { + body_status = try_match(state, &node->next_1, state->text_pos, + &next_body_position); + if (body_status < 0) + return body_status; + + if (body_status == RE_ERROR_FAILURE) + try_body = FALSE; + } else + body_status = RE_ERROR_FAILURE; + + try_tail = node->values[1] == 0; + if (try_tail) { + tail_status = try_match(state, &node->nonstring.next_2, + state->text_pos, &next_tail_position); + if (tail_status < 0) + return tail_status; + + if (tail_status == RE_ERROR_FAILURE) + try_tail = FALSE; + } else + tail_status = RE_ERROR_FAILURE; + + if (!try_body && !try_tail) + /* Neither the body nor the tail could match. */ + goto backtrack; + + if (body_status < 0 || (body_status == 0 && tail_status < 0)) + return RE_ERROR_PARTIAL; + + if (try_tail) { + if (try_body) { + /* Both the body and the tail could match, but the tail + * takes precedence. If the tail fails to match then we + * want to try the body before backtracking further. + */ + RE_MatchBodyTailStateData data_mbt; + + /* Record backtracking info for matching the body. */ + data_mbt.position = next_body_position; + data_mbt.count = rp_data->count; + data_mbt.start = rp_data->start; + data_mbt.capture_change = rp_data->capture_change; + data_mbt.index = index; + data_mbt.text_pos = state->text_pos; + + if (!ByteStack_push_block(state, &state->bstack, + (void*)&data_mbt, sizeof(data_mbt))) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, RE_OP_MATCH_BODY)) + return RE_ERROR_MEMORY; + + /* bstack: position count start capture_change index + * text_pos MATCH_BODY + */ + } + + /* Record backtracking info in case the tail fails to match. */ + if (!push_code(state, &state->bstack, index)) + return RE_ERROR_MEMORY; + if (!push_ssize(state, &state->bstack, state->text_pos)) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, RE_OP_TAIL_START)) + return RE_ERROR_MEMORY; + + /* bstack: index text_pos TAIL_START */ + + /* Advance into the tail. */ + node = next_tail_position.node; + state->text_pos = next_tail_position.text_pos; + } else { + /* Only the body could match. */ + + /* Record backtracking info in case the body fails to match. */ + if (!push_code(state, &state->bstack, index)) + return RE_ERROR_MEMORY; + if (!push_ssize(state, &state->bstack, state->text_pos)) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, RE_OP_BODY_START)) + return RE_ERROR_MEMORY; + + /* bstack: index text_pos BODY_START */ + + /* Advance into the body. */ + node = next_body_position.node; + state->text_pos = next_body_position.text_pos; + } + break; + } + case RE_OP_LAZY_REPEAT_ONE: /* Lazy repeat for one character. */ + { + RE_CODE index; + RE_RepeatData* rp_data; + size_t count; + BOOL is_partial; + TRACE(("%s %d\n", re_op_text[node->op], node->values[0])) + + /* Repeat indexes are 0-based. */ + index = node->values[0]; + rp_data = &state->repeats[index]; + + if (is_repeat_guarded(state, index, state->text_pos, + RE_STATUS_BODY)) + goto backtrack; + + /* Count how many times the character repeats, up to the minimum. + */ + count = count_one(state, node->nonstring.next_2.node, + state->text_pos, node->values[1], &is_partial); + if (is_partial) { + state->text_pos += (Py_ssize_t)count * node->step; + return RE_ERROR_PARTIAL; + } + + /* Have we matched at least the minimum? */ + if (count < node->values[1]) { + /* The repeat has failed to match at this position. */ + if (!guard_repeat(state, index, state->text_pos, + RE_STATUS_BODY, TRUE)) + return RE_ERROR_MEMORY; + goto backtrack; + } + + if (count < node->values[2]) { + /* The match is shorter than the maximum, so we might need to + * backtrack the repeat to consume more. + */ + RE_RepeatOneStateData data_ro; + + data_ro.count = rp_data->count; + data_ro.start = rp_data->start; + data_ro.node = node; + data_ro.index = index; + + if (!ByteStack_push_block(state, &state->bstack, + (void*)&data_ro, sizeof(data_ro))) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, RE_OP_LAZY_REPEAT_ONE)) + return RE_ERROR_MEMORY; + + /* bstack: count start node index LAZY_REPEAT_ONE */ + + /* Get the offset to the repeat values in the context. */ + rp_data = &state->repeats[index]; + + rp_data->start = state->text_pos; + rp_data->count = count; + } + + /* Advance into the tail. */ + state->text_pos += (Py_ssize_t)count * node->step; + node = node->next_1.node; + break; + } + case RE_OP_LOOKAROUND: /* Start of a lookaround subpattern. */ + { + RE_LookaroundStateData data_l; + BOOL has_groups; + TRACE(("%s %d\n", re_op_text[node->op], node->match)) + + data_l.node = node; + data_l.slice_start = state->slice_start; + data_l.slice_end = state->slice_end; + data_l.text_pos = state->text_pos; + + if (!ByteStack_push_block(state, &state->sstack, (void*)&data_l, + sizeof(data_l))) + return RE_ERROR_MEMORY; + has_groups = (node->status & RE_STATUS_HAS_GROUPS) != 0; + if (has_groups) { + if (!push_captures(state, &state->bstack)) + return RE_ERROR_MEMORY; + } + if (!push_bool(state, &state->bstack, has_groups)) + return RE_ERROR_MEMORY; + if (!push_fuzzy_counts(state, &state->bstack, state->fuzzy_counts)) + return RE_ERROR_MEMORY; + if (!push_size(state, &state->bstack, state->capture_change)) + return RE_ERROR_MEMORY; + if (!push_sstack(state)) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, RE_OP_LOOKAROUND)) + return RE_ERROR_MEMORY; + if (!push_bstack(state)) + return RE_ERROR_MEMORY; + + /* sstack: node slice_start slice_end text_pos + * + * bstack: [captures TRUE | FALSE] fuzzy_counts capture_change + * sstack LOOKAROUND + * + * pstack: bstack + */ + + state->slice_start = state->text_start; + state->slice_end = state->text_end; + + node = node->next_1.node; + break; + } + case RE_OP_PROPERTY: /* A property. */ + TRACE(("%s %d %d\n", re_op_text[node->op], node->match, + node->values[0])) + + if (state->text_pos >= state->text_end && state->partial_side == + RE_PARTIAL_RIGHT) + return RE_ERROR_PARTIAL; + + if (state->text_pos < state->slice_end && + matches_PROPERTY(encoding, locale_info, node, + char_at(state->text, state->text_pos)) == node->match) { + state->text_pos += node->step; + node = node->next_1.node; + } else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_item(state, search, &node, 1); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + goto backtrack; + } else + goto backtrack; + break; + case RE_OP_PROPERTY_IGN: /* A property, ignoring case. */ + TRACE(("%s %d %d\n", re_op_text[node->op], node->match, + node->values[0])) + + if (state->text_pos >= state->text_end && state->partial_side == + RE_PARTIAL_RIGHT) + return RE_ERROR_PARTIAL; + + if (state->text_pos < state->slice_end && + matches_PROPERTY_IGN(encoding, locale_info, node, + char_at(state->text, state->text_pos)) == node->match) { + state->text_pos += node->step; + node = node->next_1.node; + } else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_item(state, search, &node, 1); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + goto backtrack; + } else + goto backtrack; + break; + case RE_OP_PROPERTY_IGN_REV: /* A property, backwards, ignoring case. */ + TRACE(("%s %d %d\n", re_op_text[node->op], node->match, + node->values[0])) + + if (state->text_pos <= state->text_start && state->partial_side == RE_PARTIAL_LEFT) + return RE_ERROR_PARTIAL; + + if (state->text_pos > state->slice_start && + matches_PROPERTY_IGN(encoding, locale_info, node, + char_at(state->text, state->text_pos - 1)) == node->match) { + state->text_pos += node->step; + node = node->next_1.node; + } else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_item(state, search, &node, -1); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + goto backtrack; + } else + goto backtrack; + break; + case RE_OP_PROPERTY_REV: /* A property, backwards. */ + TRACE(("%s %d %d\n", re_op_text[node->op], node->match, + node->values[0])) + + if (state->text_pos <= state->text_start && state->partial_side == RE_PARTIAL_LEFT) + return RE_ERROR_PARTIAL; + + if (state->text_pos > state->slice_start && + matches_PROPERTY(encoding, locale_info, node, + char_at(state->text, state->text_pos - 1)) == node->match) { + state->text_pos += node->step; + node = node->next_1.node; + } else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_item(state, search, &node, -1); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + goto backtrack; + } else + goto backtrack; + break; + case RE_OP_PRUNE: /* Prune the backtracking. */ + TRACE(("%s\n", re_op_text[node->op])) + + /* bstack: ... | ... + * + * pstack: bstack + */ + + /* Prune the backtracking back to an appropriate backtracking + * point. + */ + top_bstack(state); + + /* bstack: ... + * + * pstack: bstack + */ + + node = node->next_1.node; + break; + case RE_OP_RANGE: /* A range. */ + TRACE(("%s %d %d %d\n", re_op_text[node->op], node->match, + node->values[0], node->values[1])) + + if (state->text_pos >= state->text_end && state->partial_side == + RE_PARTIAL_RIGHT) + return RE_ERROR_PARTIAL; + + if (state->text_pos < state->slice_end && matches_RANGE(encoding, + locale_info, node, char_at(state->text, state->text_pos)) == + node->match) { + state->text_pos += node->step; + node = node->next_1.node; + } else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_item(state, search, &node, 1); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + goto backtrack; + } else + goto backtrack; + break; + case RE_OP_RANGE_IGN: /* A range, ignoring case. */ + TRACE(("%s %d %d %d\n", re_op_text[node->op], node->match, + node->values[0], node->values[1])) + + if (state->text_pos >= state->text_end && state->partial_side == + RE_PARTIAL_RIGHT) + return RE_ERROR_PARTIAL; + + if (state->text_pos < state->slice_end && + matches_RANGE_IGN(encoding, locale_info, node, + char_at(state->text, state->text_pos)) == node->match) { + state->text_pos += node->step; + node = node->next_1.node; + } else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_item(state, search, &node, 1); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + goto backtrack; + } else + goto backtrack; + break; + case RE_OP_RANGE_IGN_REV: /* A range, backwards, ignoring case. */ + TRACE(("%s %d %d %d\n", re_op_text[node->op], node->match, + node->values[0], node->values[1])) + + if (state->text_pos <= state->text_start && state->partial_side == RE_PARTIAL_LEFT) + return RE_ERROR_PARTIAL; + + if (state->text_pos > state->slice_start && + matches_RANGE_IGN(encoding, locale_info, node, + char_at(state->text, state->text_pos - 1)) == node->match) { + state->text_pos += node->step; + node = node->next_1.node; + } else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_item(state, search, &node, -1); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + goto backtrack; + } else + goto backtrack; + break; + case RE_OP_RANGE_REV: /* A range, backwards. */ + TRACE(("%s %d %d %d\n", re_op_text[node->op], node->match, + node->values[0], node->values[1])) + + if (state->text_pos <= state->text_start && state->partial_side == RE_PARTIAL_LEFT) + return RE_ERROR_PARTIAL; + + if (state->text_pos > state->slice_start && matches_RANGE(encoding, + locale_info, node, char_at(state->text, state->text_pos - 1)) == + node->match) { + state->text_pos += node->step; + node = node->next_1.node; + } else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_item(state, search, &node, -1); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + goto backtrack; + } else + goto backtrack; + break; + case RE_OP_REF_GROUP: /* Reference to a capture group. */ + { + RE_GroupData* group; + RE_GroupSpan* span; + TRACE(("%s %d\n", re_op_text[node->op], node->values[0])) + + /* Capture group indexes are 1-based (excluding group 0, which is + * the entire matched string). + * + * Check whether the captured text, if any, exists at this position + * in the string. + */ + + /* Did the group capture anything? */ + group = &state->groups[node->values[0] - 1]; + if (group->current < 0) + goto backtrack; + + span = &group->captures[group->current]; + + if (string_pos < 0) + string_pos = span->start; + + /* Try comparing. */ + while (string_pos < span->end) { + if (state->text_pos >= state->text_end && + state->partial_side == RE_PARTIAL_RIGHT) + return RE_ERROR_PARTIAL; + + if (state->text_pos < state->slice_end && + same_char(char_at(state->text, state->text_pos), + char_at(state->text, string_pos))) { + ++string_pos; + ++state->text_pos; + } else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_string(state, search, node, + &string_pos, 1); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) { + string_pos = -1; + goto backtrack; + } + } else { + string_pos = -1; + goto backtrack; + } + } + + string_pos = -1; + + /* Successful match. */ + node = node->next_1.node; + break; + } + case RE_OP_REF_GROUP_FLD: /* Reference to a capture group, ignoring case. */ + { + RE_GroupData* group; + RE_GroupSpan* span; + int (*full_case_fold)(RE_LocaleInfo* locale_info, Py_UCS4 ch, + Py_UCS4* folded); + int folded_len; + int gfolded_len; + Py_UCS4 folded[RE_MAX_FOLDED]; + Py_UCS4 gfolded[RE_MAX_FOLDED]; + TRACE(("%s %d\n", re_op_text[node->op], node->values[0])) + + /* Capture group indexes are 1-based (excluding group 0, which is + * the entire matched string). + * + * Check whether the captured text, if any, exists at this position + * in the string. + */ + + /* Did the group capture anything? */ + group = &state->groups[node->values[0] - 1]; + if (group->current < 0) + goto backtrack; + + span = &group->captures[group->current]; + + full_case_fold = encoding->full_case_fold; + + if (string_pos < 0) { + string_pos = span->start; + folded_pos = 0; + folded_len = 0; + gfolded_pos = 0; + gfolded_len = 0; + } else { + folded_len = full_case_fold(locale_info, char_at(state->text, + state->text_pos), folded); + gfolded_len = full_case_fold(locale_info, char_at(state->text, + string_pos), gfolded); + } + + /* Try comparing. */ + while (string_pos < span->end) { + /* Case-fold at current position in text. */ + if (folded_pos >= folded_len) { + if (state->text_pos >= state->text_end && + state->partial_side == RE_PARTIAL_RIGHT) + return RE_ERROR_PARTIAL; + + if (state->text_pos < state->slice_end) + folded_len = full_case_fold(locale_info, + char_at(state->text, state->text_pos), folded); + else + folded_len = 0; + + folded_pos = 0; + } + + /* Case-fold at current position in group. */ + if (gfolded_pos >= gfolded_len) { + gfolded_len = full_case_fold(locale_info, + char_at(state->text, string_pos), gfolded); + gfolded_pos = 0; + } + + if (folded_pos < folded_len && same_char_ign(encoding, + locale_info, gfolded[gfolded_pos], folded[folded_pos])) { + ++folded_pos; + ++gfolded_pos; + } else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_group_fld(state, search, node, + &folded_pos, folded_len, &string_pos, &gfolded_pos, + gfolded_len, 1); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) { + string_pos = -1; + goto backtrack; + } + } else { + string_pos = -1; + goto backtrack; + } + + if (folded_pos >= folded_len && folded_len > 0) + ++state->text_pos; + + if (gfolded_pos >= gfolded_len) + ++string_pos; + } + + string_pos = -1; + + if (folded_pos < folded_len || gfolded_pos < gfolded_len) + goto backtrack; + + /* Successful match. */ + node = node->next_1.node; + break; + } + case RE_OP_REF_GROUP_FLD_REV: /* Reference to a capture group, ignoring case. */ + { + RE_GroupData* group; + RE_GroupSpan* span; + int (*full_case_fold)(RE_LocaleInfo* locale_info, Py_UCS4 ch, + Py_UCS4* folded); + int folded_len; + int gfolded_len; + Py_UCS4 folded[RE_MAX_FOLDED]; + Py_UCS4 gfolded[RE_MAX_FOLDED]; + TRACE(("%s %d\n", re_op_text[node->op], node->values[0])) + + /* Capture group indexes are 1-based (excluding group 0, which is + * the entire matched string). + * + * Check whether the captured text, if any, exists at this position + * in the string. + */ + + /* Did the group capture anything? */ + group = &state->groups[node->values[0] - 1]; + if (group->current < 0) + goto backtrack; + + span = &group->captures[group->current]; + + full_case_fold = encoding->full_case_fold; + + if (string_pos < 0) { + string_pos = span->end; + folded_pos = 0; + folded_len = 0; + gfolded_pos = 0; + gfolded_len = 0; + } else { + folded_len = full_case_fold(locale_info, char_at(state->text, + state->text_pos - 1), folded); + gfolded_len = full_case_fold(locale_info, char_at(state->text, + string_pos - 1), gfolded); + } + + /* Try comparing. */ + while (string_pos > span->start) { + /* Case-fold at current position in text. */ + if (folded_pos <= 0) { + if (state->text_pos <= state->text_start && state->partial_side == + RE_PARTIAL_LEFT) + return RE_ERROR_PARTIAL; + + if (state->text_pos > state->slice_start) + folded_len = full_case_fold(locale_info, + char_at(state->text, state->text_pos - 1), folded); + else + folded_len = 0; + + folded_pos = folded_len; + } + + /* Case-fold at current position in group. */ + if (gfolded_pos <= 0) { + gfolded_len = full_case_fold(locale_info, + char_at(state->text, string_pos - 1), gfolded); + gfolded_pos = gfolded_len; + } + + if (folded_pos > 0 && same_char_ign(encoding, locale_info, + gfolded[gfolded_pos - 1], folded[folded_pos - 1])) { + --folded_pos; + --gfolded_pos; + } else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_group_fld(state, search, node, + &folded_pos, folded_len, &string_pos, &gfolded_pos, + gfolded_len, -1); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) { + string_pos = -1; + goto backtrack; + } + } else { + string_pos = -1; + goto backtrack; + } + + if (folded_pos <= 0 && folded_len > 0) + --state->text_pos; + + if (gfolded_pos <= 0) + --string_pos; + } + + string_pos = -1; + + if (folded_pos > 0 || gfolded_pos > 0) + goto backtrack; + + /* Successful match. */ + node = node->next_1.node; + break; + } + case RE_OP_REF_GROUP_IGN: /* Reference to a capture group, ignoring case. */ + { + RE_GroupData* group; + RE_GroupSpan* span; + TRACE(("%s %d\n", re_op_text[node->op], node->values[0])) + + /* Capture group indexes are 1-based (excluding group 0, which is + * the entire matched string). + * + * Check whether the captured text, if any, exists at this position + * in the string. + */ + + /* Did the group capture anything? */ + group = &state->groups[node->values[0] - 1]; + if (group->current < 0) + goto backtrack; + + span = &group->captures[group->current]; + + if (string_pos < 0) + string_pos = span->start; + + /* Try comparing. */ + while (string_pos < span->end) { + if (state->text_pos >= state->text_end && + state->partial_side == RE_PARTIAL_RIGHT) + return RE_ERROR_PARTIAL; + + if (state->text_pos < state->slice_end && + same_char_ign(encoding, locale_info, char_at(state->text, + state->text_pos), char_at(state->text, string_pos))) { + ++string_pos; + ++state->text_pos; + } else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_string(state, search, node, + &string_pos, 1); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) { + string_pos = -1; + goto backtrack; + } + } else { + string_pos = -1; + goto backtrack; + } + } + + string_pos = -1; + + /* Successful match. */ + node = node->next_1.node; + break; + } + case RE_OP_REF_GROUP_IGN_REV: /* Reference to a capture group, ignoring case. */ + { + RE_GroupData* group; + RE_GroupSpan* span; + TRACE(("%s %d\n", re_op_text[node->op], node->values[0])) + + /* Capture group indexes are 1-based (excluding group 0, which is + * the entire matched string). + * + * Check whether the captured text, if any, exists at this position + * in the string. + */ + + /* Did the group capture anything? */ + group = &state->groups[node->values[0] - 1]; + if (group->current < 0) + goto backtrack; + + span = &group->captures[group->current]; + + if (string_pos < 0) + string_pos = span->end; + + /* Try comparing. */ + while (string_pos > span->start) { + if (state->text_pos <= state->text_start && state->partial_side == + RE_PARTIAL_LEFT) + return RE_ERROR_PARTIAL; + + if (state->text_pos > state->slice_start && + same_char_ign(encoding, locale_info, char_at(state->text, + state->text_pos - 1), char_at(state->text, string_pos - 1))) + { + --string_pos; + --state->text_pos; + } else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_string(state, search, node, + &string_pos, -1); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) { + string_pos = -1; + goto backtrack; + } + } else { + string_pos = -1; + goto backtrack; + } + } + + string_pos = -1; + + /* Successful match. */ + node = node->next_1.node; + break; + } + case RE_OP_REF_GROUP_REV: /* Reference to a capture group. */ + { + RE_GroupData* group; + RE_GroupSpan* span; + TRACE(("%s %d\n", re_op_text[node->op], node->values[0])) + + /* Capture group indexes are 1-based (excluding group 0, which is + * the entire matched string). + * + * Check whether the captured text, if any, exists at this position + * in the string. + */ + + /* Did the group capture anything? */ + group = &state->groups[node->values[0] - 1]; + if (group->current < 0) + goto backtrack; + + span = &group->captures[group->current]; + + if (string_pos < 0) + string_pos = span->end; + + /* Try comparing. */ + while (string_pos > span->start) { + if (state->text_pos <= state->text_start && state->partial_side == + RE_PARTIAL_LEFT) + return RE_ERROR_PARTIAL; + + if (state->text_pos > state->slice_start && + same_char(char_at(state->text, state->text_pos - 1), + char_at(state->text, string_pos - 1))) { + --string_pos; + --state->text_pos; + } else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_string(state, search, node, + &string_pos, -1); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) { + string_pos = -1; + goto backtrack; + } + } else { + string_pos = -1; + goto backtrack; + } + } + + string_pos = -1; + + /* Successful match. */ + node = node->next_1.node; + break; + } + case RE_OP_SEARCH_ANCHOR: /* At the start of the search. */ + TRACE(("%s %d\n", re_op_text[node->op], node->values[0])) + + if (state->text_pos == state->search_anchor) + node = node->next_1.node; + else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_item(state, search, &node, 0); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + goto backtrack; + } else + goto backtrack; + break; + case RE_OP_SET_DIFF: /* Set difference. */ + case RE_OP_SET_INTER: /* Set intersection. */ + case RE_OP_SET_SYM_DIFF: /* Set symmetric difference. */ + case RE_OP_SET_UNION: /* Set union. */ + TRACE(("%s %d\n", re_op_text[node->op], node->match)) + + if (state->text_pos >= state->text_end && state->partial_side == + RE_PARTIAL_RIGHT) + return RE_ERROR_PARTIAL; + + if (state->text_pos < state->slice_end && matches_SET(encoding, + locale_info, node, char_at(state->text, state->text_pos)) == + node->match) { + state->text_pos += node->step; + node = node->next_1.node; + } else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_item(state, search, &node, 1); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + goto backtrack; + } else + goto backtrack; + break; + case RE_OP_SET_DIFF_IGN: /* Set difference, ignoring case. */ + case RE_OP_SET_INTER_IGN: /* Set intersection, ignoring case. */ + case RE_OP_SET_SYM_DIFF_IGN: /* Set symmetric difference, ignoring case. */ + case RE_OP_SET_UNION_IGN: /* Set union, ignoring case. */ + TRACE(("%s %d\n", re_op_text[node->op], node->match)) + + if (state->text_pos >= state->text_end && state->partial_side == + RE_PARTIAL_RIGHT) + return RE_ERROR_PARTIAL; + + if (state->text_pos < state->slice_end && matches_SET_IGN(encoding, + locale_info, node, char_at(state->text, state->text_pos)) == + node->match) { + state->text_pos += node->step; + node = node->next_1.node; + } else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_item(state, search, &node, 1); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + goto backtrack; + } else + goto backtrack; + break; + case RE_OP_SET_DIFF_IGN_REV: /* Set difference, ignoring case. */ + case RE_OP_SET_INTER_IGN_REV: /* Set intersection, ignoring case. */ + case RE_OP_SET_SYM_DIFF_IGN_REV: /* Set symmetric difference, ignoring case. */ + case RE_OP_SET_UNION_IGN_REV: /* Set union, ignoring case. */ + TRACE(("%s %d\n", re_op_text[node->op], node->match)) + + if (state->text_pos <= state->text_start && state->partial_side == RE_PARTIAL_LEFT) + return RE_ERROR_PARTIAL; + + if (state->text_pos > state->slice_start && + matches_SET_IGN(encoding, locale_info, node, char_at(state->text, + state->text_pos - 1)) == node->match) { + state->text_pos += node->step; + node = node->next_1.node; + } else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_item(state, search, &node, -1); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + goto backtrack; + } else + goto backtrack; + break; + case RE_OP_SET_DIFF_REV: /* Set difference. */ + case RE_OP_SET_INTER_REV: /* Set intersection. */ + case RE_OP_SET_SYM_DIFF_REV: /* Set symmetric difference. */ + case RE_OP_SET_UNION_REV: /* Set union. */ + TRACE(("%s %d\n", re_op_text[node->op], node->match)) + + if (state->text_pos <= state->text_start && state->partial_side == RE_PARTIAL_LEFT) + return RE_ERROR_PARTIAL; + + if (state->text_pos > state->slice_start && matches_SET(encoding, + locale_info, node, char_at(state->text, state->text_pos - 1)) == + node->match) { + state->text_pos += node->step; + node = node->next_1.node; + } else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_item(state, search, &node, -1); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + goto backtrack; + } else + goto backtrack; + break; + case RE_OP_SKIP: /* Skip the part of the text already matched. */ + TRACE(("%s\n", re_op_text[node->op])) + + /* bstack: ... | ... + * + * pstack: bstack + */ + + if (node->status & RE_STATUS_REVERSE) + state->slice_end = state->text_pos; + else + state->slice_start = state->text_pos; + + /* Prune the backtracking back to an appropriate backtracking + * point. + */ + top_bstack(state); + + /* bstack: ... + * + * pstack: bstack + */ + + node = node->next_1.node; + break; + case RE_OP_START_GROUP: /* Start of a capture group. */ + { + RE_CODE private_index; + RE_CODE public_index; + RE_GroupData* group; + BOOL capture; + TRACE(("%s %d\n", re_op_text[node->op], node->values[1])) + + /* Capture group indexes are 1-based (excluding group 0, which is + * the entire matched string). + */ + private_index = node->values[0]; + public_index = node->values[1]; + group = &state->groups[private_index - 1]; + capture = (BOOL)node->values[2]; + + if (capture) { + RE_GroupSpan span; + RE_GroupStateData data_g; + + /* sstack: end + * + * bstack: - + */ + + if (!pop_ssize(state, &state->sstack, &span.end)) + return RE_ERROR_MEMORY; + + span.start = state->text_pos; + + data_g.text_pos = span.end; + data_g.current = group->current; + data_g.capture_change = state->capture_change; + data_g.private_index = private_index; + data_g.public_index = public_index; + + if (!ByteStack_push_block(state, &state->bstack, + (void*)&data_g, sizeof(data_g))) + return RE_ERROR_MEMORY; + + if (pattern->group_info[private_index - 1].referenced && + !same_span_as_group(group, span)) + ++state->capture_change; + + if (!save_capture(state, private_index, public_index, span)) + return RE_ERROR_MEMORY; + group->current = (Py_ssize_t)group->count - 1; + } else { + if (!push_ssize(state, &state->sstack, state->text_pos)) + return RE_ERROR_MEMORY; + } + + if (!push_bool(state, &state->bstack, capture)) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, RE_OP_START_GROUP)) + return RE_ERROR_MEMORY; + + /* If capturing: + * + * sstack: - + * + * bstack: end current capture_change private_index public_index + * TRUE START_GROUP + * + * else: + * + * sstack: start + * + * bstack: FALSE START_GROUP + */ + + node = node->next_1.node; + break; + } + case RE_OP_START_OF_LINE: /* At the start of a line. */ + TRACE(("%s\n", re_op_text[node->op])) + + status = try_match_START_OF_LINE(state, node, state->text_pos); + if (status < 0) + return status; + + if (status == RE_ERROR_SUCCESS) + node = node->next_1.node; + else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_item(state, search, &node, 0); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + goto backtrack; + } else + goto backtrack; + break; + case RE_OP_START_OF_LINE_U: /* At the start of a line. */ + TRACE(("%s\n", re_op_text[node->op])) + + status = try_match_START_OF_LINE_U(state, node, state->text_pos); + if (status < 0) + return status; + + if (status == RE_ERROR_SUCCESS) + node = node->next_1.node; + else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_item(state, search, &node, 0); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + goto backtrack; + } else + goto backtrack; + break; + case RE_OP_START_OF_STRING: /* At the start of the string. */ + TRACE(("%s\n", re_op_text[node->op])) + + status = try_match_START_OF_STRING(state, node, state->text_pos); + if (status < 0) + return status; + + if (status == RE_ERROR_SUCCESS) + node = node->next_1.node; + else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_item(state, search, &node, 0); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + goto backtrack; + } else + goto backtrack; + break; + case RE_OP_START_OF_WORD: /* At the start of a word. */ + TRACE(("%s\n", re_op_text[node->op])) + + status = try_match_START_OF_WORD(state, node, state->text_pos); + if (status < 0) + return status; + + if (status == RE_ERROR_SUCCESS) + node = node->next_1.node; + else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_item(state, search, &node, 0); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + goto backtrack; + } else + goto backtrack; + break; + case RE_OP_STRING: /* A string. */ + { + Py_ssize_t length; + RE_CODE* values; + TRACE(("%s %zd\n", re_op_text[node->op], node->value_count)) + + if ((node->status & RE_STATUS_REQUIRED) && state->text_pos == + state->req_pos && string_pos < 0) + state->text_pos = state->req_end; + else { + length = (Py_ssize_t)node->value_count; + + if (string_pos < 0) + string_pos = 0; + + values = node->values; + + /* Try comparing. */ + while (string_pos < length) { + if (state->text_pos >= state->text_end && + state->partial_side == RE_PARTIAL_RIGHT) + return RE_ERROR_PARTIAL; + + if (state->text_pos < state->slice_end && + same_char(char_at(state->text, state->text_pos), + values[string_pos])) { + ++string_pos; + ++state->text_pos; + } else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_string(state, search, node, + &string_pos, 1); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) { + string_pos = -1; + goto backtrack; + } + } else { + string_pos = -1; + goto backtrack; + } + } + } + + if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_insert(state, 1, node->next_1.node); + if (status < 0) + return status; + } + + string_pos = -1; + + /* Successful match. */ + node = node->next_1.node; + break; + } + case RE_OP_STRING_FLD: /* A string, ignoring case. */ + { + Py_ssize_t length; + int (*full_case_fold)(RE_LocaleInfo* locale_info, Py_UCS4 ch, + Py_UCS4* folded); + RE_CODE* values; + int folded_len; + Py_UCS4 folded[RE_MAX_FOLDED]; + TRACE(("%s %zd\n", re_op_text[node->op], node->value_count)) + + if ((node->status & RE_STATUS_REQUIRED) && state->text_pos == + state->req_pos && string_pos < 0) + state->text_pos = state->req_end; + else { + length = (Py_ssize_t)node->value_count; + + full_case_fold = encoding->full_case_fold; + + if (string_pos < 0) { + string_pos = 0; + folded_pos = 0; + folded_len = 0; + } else { + folded_len = full_case_fold(locale_info, + char_at(state->text, state->text_pos), folded); + if (folded_pos >= folded_len) { + if (state->text_pos >= state->slice_end) + goto backtrack; + + ++state->text_pos; + folded_pos = 0; + folded_len = 0; + } + } + + values = node->values; + + /* Try comparing. */ + while (string_pos < length) { + if (folded_pos >= folded_len) { + if (state->text_pos >= state->text_end && + state->partial_side == RE_PARTIAL_RIGHT) + return RE_ERROR_PARTIAL; + + if (state->text_pos < state->slice_end) + folded_len = full_case_fold(locale_info, + char_at(state->text, state->text_pos), folded); + else + folded_len = 0; + + folded_pos = 0; + } + + if (folded_pos < folded_len && same_char_ign(encoding, + locale_info, values[string_pos], folded[folded_pos])) { + ++string_pos; + ++folded_pos; + + if (folded_pos >= folded_len) + ++state->text_pos; + } else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_string_fld(state, search, node, + &string_pos, &folded_pos, folded_len, 1); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) { + string_pos = -1; + goto backtrack; + } + + if (folded_pos >= folded_len && folded_len > 0) + ++state->text_pos; + } else { + string_pos = -1; + goto backtrack; + } + } + + if (node->status & RE_STATUS_FUZZY) { + while (folded_pos < folded_len) { + status = fuzzy_match_string_fld(state, search, node, + &string_pos, &folded_pos, folded_len, 1); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) { + string_pos = -1; + goto backtrack; + } + + if (folded_pos >= folded_len && folded_len > 0) + ++state->text_pos; + } + } + + string_pos = -1; + + if (folded_pos < folded_len) + goto backtrack; + } + + /* Successful match. */ + node = node->next_1.node; + break; + } + case RE_OP_STRING_FLD_REV: /* A string, ignoring case. */ + { + Py_ssize_t length; + int (*full_case_fold)(RE_LocaleInfo* locale_info, Py_UCS4 ch, + Py_UCS4* folded); + RE_CODE* values; + int folded_len; + Py_UCS4 folded[RE_MAX_FOLDED]; + TRACE(("%s %zd\n", re_op_text[node->op], node->value_count)) + + if ((node->status & RE_STATUS_REQUIRED) && state->text_pos == + state->req_pos && string_pos < 0) + state->text_pos = state->req_end; + else { + length = (Py_ssize_t)node->value_count; + + full_case_fold = encoding->full_case_fold; + + if (string_pos < 0) { + string_pos = length; + folded_pos = 0; + folded_len = 0; + } else { + folded_len = full_case_fold(locale_info, + char_at(state->text, state->text_pos - 1), folded); + if (folded_pos <= 0) { + if (state->text_pos <= state->slice_start) + goto backtrack; + + --state->text_pos; + folded_pos = 0; + folded_len = 0; + } + } + + values = node->values; + + /* Try comparing. */ + while (string_pos > 0) { + if (folded_pos <= 0) { + if (state->text_pos <= state->text_start && state->partial_side == + RE_PARTIAL_LEFT) + return RE_ERROR_PARTIAL; + + if (state->text_pos > state->slice_start) + folded_len = full_case_fold(locale_info, + char_at(state->text, state->text_pos - 1), + folded); + else + folded_len = 0; + + folded_pos = folded_len; + } + + if (folded_pos > 0 && same_char_ign(encoding, locale_info, + values[string_pos - 1], folded[folded_pos - 1])) { + --string_pos; + --folded_pos; + + if (folded_pos <= 0) + --state->text_pos; + } else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_string_fld(state, search, node, + &string_pos, &folded_pos, folded_len, -1); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) { + string_pos = -1; + goto backtrack; + } + + if (folded_pos <= 0 && folded_len > 0) + --state->text_pos; + } else { + string_pos = -1; + goto backtrack; + } + } + + if (node->status & RE_STATUS_FUZZY) { + while (folded_pos > 0) { + status = fuzzy_match_string_fld(state, search, node, + &string_pos, &folded_pos, folded_len, -1); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) { + string_pos = -1; + goto backtrack; + } + + if (folded_pos <= 0 && folded_len > 0) + --state->text_pos; + } + } + + string_pos = -1; + + if (folded_pos > 0) + goto backtrack; + } + + /* Successful match. */ + node = node->next_1.node; + break; + } + case RE_OP_STRING_IGN: /* A string, ignoring case. */ + { + Py_ssize_t length; + RE_CODE* values; + TRACE(("%s %zd\n", re_op_text[node->op], node->value_count)) + + if ((node->status & RE_STATUS_REQUIRED) && state->text_pos == + state->req_pos && string_pos < 0) + state->text_pos = state->req_end; + else { + length = (Py_ssize_t)node->value_count; + + if (string_pos < 0) + string_pos = 0; + + values = node->values; + + /* Try comparing. */ + while (string_pos < length) { + if (state->text_pos >= state->text_end && + state->partial_side == RE_PARTIAL_RIGHT) + return RE_ERROR_PARTIAL; + + if (state->text_pos < state->slice_end && + same_char_ign(encoding, locale_info, char_at(state->text, + state->text_pos), values[string_pos])) { + ++string_pos; + ++state->text_pos; + } else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_string(state, search, node, + &string_pos, 1); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) { + string_pos = -1; + goto backtrack; + } + } else { + string_pos = -1; + goto backtrack; + } + } + } + + if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_insert(state, 1, node->next_1.node); + if (status < 0) + return status; + } + + string_pos = -1; + + /* Successful match. */ + node = node->next_1.node; + break; + } + case RE_OP_STRING_IGN_REV: /* A string, ignoring case. */ + { + Py_ssize_t length; + RE_CODE* values; + TRACE(("%s %zd\n", re_op_text[node->op], node->value_count)) + + if ((node->status & RE_STATUS_REQUIRED) && state->text_pos == + state->req_pos && string_pos < 0) + state->text_pos = state->req_end; + else { + length = (Py_ssize_t)node->value_count; + + if (string_pos < 0) + string_pos = length; + + values = node->values; + + /* Try comparing. */ + while (string_pos > 0) { + if (state->text_pos <= state->text_start && state->partial_side == + RE_PARTIAL_LEFT) + return RE_ERROR_PARTIAL; + + if (state->text_pos > state->slice_start && + same_char_ign(encoding, locale_info, char_at(state->text, + state->text_pos - 1), values[string_pos - 1])) { + --string_pos; + --state->text_pos; + } else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_string(state, search, node, + &string_pos, -1); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) { + string_pos = -1; + goto backtrack; + } + } else { + string_pos = -1; + goto backtrack; + } + } + } + + if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_insert(state, -1, node->next_1.node); + if (status < 0) + return status; + } + + string_pos = -1; + + /* Successful match. */ + node = node->next_1.node; + break; + } + case RE_OP_STRING_REV: /* A string. */ + { + Py_ssize_t length; + RE_CODE* values; + TRACE(("%s %zd\n", re_op_text[node->op], node->value_count)) + + if ((node->status & RE_STATUS_REQUIRED) && state->text_pos == + state->req_pos && string_pos < 0) + state->text_pos = state->req_end; + else { + length = (Py_ssize_t)node->value_count; + + if (string_pos < 0) + string_pos = length; + + values = node->values; + + /* Try comparing. */ + while (string_pos > 0) { + if (state->text_pos <= state->text_start && state->partial_side == + RE_PARTIAL_LEFT) + return RE_ERROR_PARTIAL; + + if (state->text_pos > state->slice_start && + same_char(char_at(state->text, state->text_pos - 1), + values[string_pos - 1])) { + --string_pos; + --state->text_pos; + } else if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_match_string(state, search, node, + &string_pos, -1); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) { + string_pos = -1; + goto backtrack; + } + } else { + string_pos = -1; + goto backtrack; + } + } + } + + if (node->status & RE_STATUS_FUZZY) { + status = fuzzy_insert(state, -1, node->next_1.node); + if (status < 0) + return status; + } + + string_pos = -1; + + /* Successful match. */ + node = node->next_1.node; + break; + } + case RE_OP_SUCCESS: /* Success. */ + /* Must the match advance past its start? */ + TRACE(("%s\n", re_op_text[node->op])) + + if (state->text_pos == state->search_anchor && state->must_advance) + goto backtrack; + + if (state->match_all) { + /* We want to match all of the slice. */ + if (state->reverse) { + if (state->text_pos != state->slice_start) + goto backtrack; + } else { + if (state->text_pos != state->slice_end) + goto backtrack; + } + } + + if (state->pattern->flags & RE_FLAG_POSIX) { + /* If we're looking for a POSIX match, check whether this one + * is better and then keep looking. + */ + if (!check_posix_match(state)) + return RE_ERROR_MEMORY; + + goto backtrack; + } + + return RE_ERROR_SUCCESS; + default: /* Illegal opcode! */ + TRACE(("UNKNOWN OP %d\n", node->op)) + return RE_ERROR_ILLEGAL; + } + } + +backtrack: + for (;;) { + RE_UINT8 op; + TRACE(("BACKTRACK ")) + + /* Should we abort the matching? */ + state->iterations += 0x100U; + + if (state->iterations == 0 && safe_check_cancel(state)) + return RE_ERROR_CANCELLED; + + if (!pop_uint8(state, &state->bstack, &op)) + return RE_ERROR_MEMORY; + + switch (op) { + case RE_OP_ANY: /* Any character except a newline. */ + case RE_OP_ANY_ALL: /* Any character at all. */ + case RE_OP_ANY_ALL_REV: /* Any character at all, backwards. */ + case RE_OP_ANY_REV: /* Any character except a newline, backwards. */ + case RE_OP_ANY_U: /* Any character except a line separator. */ + case RE_OP_ANY_U_REV: /* Any character except a line separator, backwards. */ + case RE_OP_CHARACTER: /* A character. */ + case RE_OP_CHARACTER_IGN: /* A character, ignoring case. */ + case RE_OP_CHARACTER_IGN_REV: /* A character, ignoring case, backwards. */ + case RE_OP_CHARACTER_REV: /* A character, backwards. */ + case RE_OP_PROPERTY: /* A property. */ + case RE_OP_PROPERTY_IGN: /* A property, ignoring case. */ + case RE_OP_PROPERTY_IGN_REV: /* A property, ignoring case, backwards. */ + case RE_OP_PROPERTY_REV: /* A property, backwards. */ + case RE_OP_RANGE: /* A range. */ + case RE_OP_RANGE_IGN: /* A range, ignoring case. */ + case RE_OP_RANGE_IGN_REV: /* A range, ignoring case, backwards. */ + case RE_OP_RANGE_REV: /* A range, backwards. */ + case RE_OP_SET_DIFF: /* Set difference. */ + case RE_OP_SET_DIFF_IGN: /* Set difference, ignoring case. */ + case RE_OP_SET_DIFF_IGN_REV: /* Set difference, ignoring case, backwards. */ + case RE_OP_SET_DIFF_REV: /* Set difference, backwards. */ + case RE_OP_SET_INTER: /* Set intersection. */ + case RE_OP_SET_INTER_IGN: /* Set intersection, ignoring case. */ + case RE_OP_SET_INTER_IGN_REV: /* Set intersection, ignoring case, backwards. */ + case RE_OP_SET_INTER_REV: /* Set intersection, backwards. */ + case RE_OP_SET_SYM_DIFF: /* Set symmetric difference. */ + case RE_OP_SET_SYM_DIFF_IGN: /* Set symmetric difference, ignoring case. */ + case RE_OP_SET_SYM_DIFF_IGN_REV: /* Set symmetric difference, ignoring case, backwards. */ + case RE_OP_SET_SYM_DIFF_REV: /* Set symmetric difference, backwards. */ + case RE_OP_SET_UNION: /* Set union. */ + case RE_OP_SET_UNION_IGN: /* Set union, ignoring case. */ + case RE_OP_SET_UNION_IGN_REV: /* Set union, ignoring case, backwards. */ + case RE_OP_SET_UNION_REV: /* Set union, backwards. */ + TRACE(("%s\n", re_op_text[op])) + + status = retry_fuzzy_match_item(state, op, search, &node, TRUE); + if (status < 0) + return status; + + if (status == RE_ERROR_SUCCESS) + goto advance; + break; + case RE_OP_ATOMIC: /* Start of an atomic group. */ + TRACE(("%s\n", re_op_text[op])) + + /* sstack: ... + * + * bstack: captures fuzzy_counts capture_change sstack + * + * pstack: bstack + */ + + if (!drop_bstack(state)) + return RE_ERROR_MEMORY; + if (!pop_sstack(state)) + return RE_ERROR_MEMORY; + + /* sstack: - + * + * bstack: captures fuzzy_counts capture_change + * + * pstack: - + */ + + if (!pop_size(state, &state->bstack, &state->capture_change)) + return RE_ERROR_MEMORY; + if (!pop_fuzzy_counts(state, &state->bstack, state->fuzzy_counts)) + return RE_ERROR_MEMORY; + if (!pop_captures(state, &state->bstack)) + return RE_ERROR_MEMORY; + break; + case RE_OP_BODY_END: + { + RE_BodyEndStateData data_be; + size_t capture_change; + RE_CODE index; + Py_ssize_t start; + size_t count; + RE_RepeatData* rp_data; + + /* bstack: count start capture_change index */ + + if (!ByteStack_pop_block(state, &state->bstack, (void*)&data_be, + sizeof(data_be))) + return RE_ERROR_MEMORY; + + index = data_be.index; + capture_change = data_be.capture_change; + start = data_be.start; + count = data_be.count; + TRACE(("%s %u\n", re_op_text[op], (unsigned int)index)) + + /* We're backtracking into the body. */ + rp_data = &state->repeats[index]; + + /* Restore the repeat info. */ + rp_data->count = count; + rp_data->start = start; + rp_data->capture_change = capture_change; + break; + } + case RE_OP_BODY_START: + { + Py_ssize_t text_pos; + RE_CODE index; + + /* bstack: index text_pos */ + + if (!pop_ssize(state, &state->bstack, &text_pos)) + return RE_ERROR_MEMORY; + if (!pop_code(state, &state->bstack, &index)) + return RE_ERROR_MEMORY; + TRACE(("%s %u\n", re_op_text[op], (unsigned int)index)) + + /* The body may have failed to match at this position. */ + if (!guard_repeat(state, index, text_pos, RE_STATUS_BODY, TRUE)) + return RE_ERROR_MEMORY; + break; + } + case RE_OP_BOUNDARY: /* At a word boundary. */ + case RE_OP_DEFAULT_BOUNDARY: /* At a default word boundary. */ + case RE_OP_DEFAULT_END_OF_WORD: /* At the default end of a word. */ + case RE_OP_DEFAULT_START_OF_WORD: /* At the default start of a word. */ + case RE_OP_END_OF_LINE: /* At the end of a line. */ + case RE_OP_END_OF_LINE_U: /* At the end of a line. */ + case RE_OP_END_OF_STRING: /* At the end of the string. */ + case RE_OP_END_OF_STRING_LINE: /* At the end of string or final newline. */ + case RE_OP_END_OF_STRING_LINE_U: /* At the end of string or final newline. */ + case RE_OP_END_OF_WORD: /* At the end of a word. */ + case RE_OP_GRAPHEME_BOUNDARY: /* On a grapheme boundary. */ + case RE_OP_START_OF_LINE: /* At the start of a line. */ + case RE_OP_START_OF_LINE_U: /* At the start of a line. */ + case RE_OP_START_OF_STRING: /* At the start of the string. */ + case RE_OP_START_OF_WORD: /* At the start of a word. */ + TRACE(("%s\n", re_op_text[op])) + + status = retry_fuzzy_match_item(state, op, search, &node, FALSE); + if (status < 0) + return status; + + if (status == RE_ERROR_SUCCESS) + goto advance; + break; + case RE_OP_BRANCH: /* 2-way branch. */ + TRACE(("%s\n", re_op_text[op])) + + /* sstack: - + * + * bstack: text_pos node + */ + + if (!pop_pointer(state, &state->bstack, (void*)&node)) + return RE_ERROR_MEMORY; + if (!pop_ssize(state, &state->bstack, &state->text_pos)) + return RE_ERROR_MEMORY; + goto advance; + case RE_OP_CALL_REF: /* A group call ref. */ + TRACE(("%s\n", re_op_text[op])) + + /* sstack: NULL + * + * bstack: - + */ + + if (!drop_pointer(state, &state->sstack)) + return RE_ERROR_MEMORY; + break; + case RE_OP_CONDITIONAL: /* Conditional subpattern. */ + { + RE_Node* conditional; + RE_LookaroundStateData data_l; + TRACE(("%s\n", re_op_text[op])) + + /* sstack: node slice_start slice_end text_pos ... + * + * bstack: captures repeats fuzzy_counts capture_change sstack + * + * pstack: bstack + */ + + if (!drop_bstack(state)) + return RE_ERROR_MEMORY; + if (!pop_sstack(state)) + return RE_ERROR_MEMORY; + + /* sstack: node slice_start slice_end text_pos + * + * bstack: captures repeats fuzzy_counts capture_change + * + * pstack: - + */ + + if (!ByteStack_pop_block(state, &state->sstack, (void*)&data_l, + sizeof(data_l))) + return RE_ERROR_MEMORY; + + state->text_pos = data_l.text_pos; + state->slice_end = data_l.slice_end; + state->slice_start = data_l.slice_start; + conditional = data_l.node; + + /* sstack: - + * + * bstack: captures repeats fuzzy_counts capture_change + * + * pstack: - + */ + + if (!pop_size(state, &state->bstack, &state->capture_change)) + return RE_ERROR_MEMORY; + if (!pop_fuzzy_counts(state, &state->bstack, state->fuzzy_counts)) + return RE_ERROR_MEMORY; + if (!pop_repeats(state, &state->bstack)) + return RE_ERROR_MEMORY; + if (!pop_captures(state, &state->bstack)) + return RE_ERROR_MEMORY; + + /* sstack: - + * + * bstack: - + * + * pstack: - + */ + + if (conditional->match) + /* It's a positive conditional that's failed. Go to the 'false' + * 'false' branch. + */ + node = conditional->nonstring.next_2.node; + else + /* It's a negative lookaround that's failed. Go to the 'true' + * branch. + */ + node = conditional->nonstring.true_node; + + goto advance; + } + case RE_OP_END_ATOMIC: /* End of an atomic group. */ + TRACE(("%s\n", re_op_text[op])) + + /* bstack: captures fuzzy_counts capture_change */ + + if (!pop_size(state, &state->bstack, &state->capture_change)) + return RE_ERROR_MEMORY; + if (!pop_fuzzy_counts(state, &state->bstack, state->fuzzy_counts)) + return RE_ERROR_MEMORY; + if (!pop_captures(state, &state->bstack)) + return RE_ERROR_MEMORY; + break; + case RE_OP_END_CONDITIONAL: /* End of a conditional subpattern. */ + { + TRACE(("%s\n", re_op_text[op])) + + /* sstack: - + * + * bstack: captures repeats fuzzy_counts capture_change + * + * pstack: - + */ + + if (!pop_size(state, &state->bstack, &state->capture_change)) + return RE_ERROR_MEMORY; + if (!pop_fuzzy_counts(state, &state->bstack, state->fuzzy_counts)) + return RE_ERROR_MEMORY; + if (!pop_repeats(state, &state->bstack)) + return RE_ERROR_MEMORY; + if (!pop_captures(state, &state->bstack)) + return RE_ERROR_MEMORY; + + /* sstack: - + * + * bstack: - + * + * pstack: - + */ + break; + } + case RE_OP_END_FUZZY: /* End of fuzzy matching. */ + { + RE_Node* inner_node; + size_t inner_counts[RE_FUZZY_COUNT]; + size_t insertions; + TRACE(("%s\n", re_op_text[op])) + + /* sstack: - + * + * bstack: inner_counts inner_node text_pos end_fuzzy_node + */ + + if (!pop_pointer(state, &state->bstack, (void*)&node)) + return RE_ERROR_MEMORY; + if (!pop_ssize(state, &state->bstack, &state->text_pos)) + return RE_ERROR_MEMORY; + if (!pop_pointer(state, &state->bstack, (void*)&inner_node)) + return RE_ERROR_MEMORY; + if (!pop_size(state, &state->bstack, &insertions)) + return RE_ERROR_MEMORY; + if (!pop_fuzzy_counts(state, &state->bstack, inner_counts)) + return RE_ERROR_MEMORY; + + /* sstack: - + * + * bstack: - + */ + + if (insertion_permitted(state, inner_node, inner_counts) && + total_errors(state->fuzzy_counts) + total_errors(inner_counts) < + state->max_errors && fuzzy_ext_match(state, inner_node, + state->text_pos)) { + RE_INT8 step; + Py_ssize_t limit; + + /* Try another insertion. */ + if (inner_node->status & RE_STATUS_REVERSE) { + step = -1; + limit = state->slice_start; + } else { + step = 1; + limit = state->slice_end; + } + + if (state->text_pos != limit) { + if (!record_fuzzy(state, RE_FUZZY_INS, state->text_pos)) + return RE_ERROR_MEMORY; + ++inner_counts[RE_FUZZY_INS]; + + state->text_pos += step; + + /* Save the inner fuzzy info. */ + if (!push_fuzzy_counts(state, &state->bstack, + inner_counts)) + return RE_ERROR_MEMORY; + if (!push_size(state, &state->bstack, insertions + 1)) + return RE_ERROR_MEMORY; + if (!push_pointer(state, &state->bstack, inner_node)) + return RE_ERROR_MEMORY; + if (!push_ssize(state, &state->bstack, state->text_pos)) + return RE_ERROR_MEMORY; + if (!push_pointer(state, &state->bstack, node)) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, RE_OP_END_FUZZY)) + return RE_ERROR_MEMORY; + + /* sstack: - + * + * bstack: inner_counts inner_node text_pos end_fuzzy_node + * END_FUZZY + */ + + ++state->fuzzy_counts[RE_FUZZY_INS]; + state->total_errors = total_errors(state->fuzzy_counts); + + node = node->next_1.node; + goto advance; + } + } + + /* Subtract the inner counts from the outer counts. */ + state->fuzzy_counts[RE_FUZZY_SUB] -= inner_counts[RE_FUZZY_SUB]; + state->fuzzy_counts[RE_FUZZY_INS] -= inner_counts[RE_FUZZY_INS]; + state->fuzzy_counts[RE_FUZZY_DEL] -= inner_counts[RE_FUZZY_DEL]; + + /* Save the outer fuzzy info. */ + if (!push_fuzzy_counts(state, &state->sstack, state->fuzzy_counts)) + return RE_ERROR_MEMORY; + if (!push_pointer(state, &state->sstack, state->fuzzy_node)) + return RE_ERROR_MEMORY; + + /* sstack: outer_counts outer_node + * + * bstack: - + */ + + inner_counts[RE_FUZZY_INS] -= insertions; + while (insertions > 0) { + unrecord_fuzzy(state); + --insertions; + } + + /* Restore the inner fuzzy info. */ + Py_MEMCPY(state->fuzzy_counts, inner_counts, + sizeof(state->fuzzy_counts)); + state->fuzzy_node = inner_node; + break; + } + case RE_OP_END_GROUP: /* End of a capture group. */ + { + BOOL capture; + TRACE(("%s\n", re_op_text[op])) + + /* If capturing: + * + * sstack: - + * + * bstack: start current capture_change private_index public_index + * TRUE + * + * else: + * + * sstack: end + * + * bstack: FALSE + */ + + if (!pop_bool(state, &state->bstack, &capture)) + return RE_ERROR_MEMORY; + + if (capture) { + RE_GroupStateData data_g; + RE_CODE public_index; + RE_CODE private_index; + Py_ssize_t start; + RE_GroupData* group; + + if (!ByteStack_pop_block(state, &state->bstack, (void*)&data_g, + sizeof(data_g))) + return RE_ERROR_MEMORY; + + public_index = data_g.public_index; + private_index = data_g.private_index; + state->capture_change = data_g.capture_change; + group = &state->groups[private_index - 1]; + group->current = data_g.current; + start = data_g.text_pos; + if (!push_ssize(state, &state->sstack, start)) + return RE_ERROR_MEMORY; + + unsave_capture(state, private_index, public_index); + + /* sstack: start + * + * bstack: - + */ + } else { + if (!drop_ssize(state, &state->sstack)) + return RE_ERROR_MEMORY; + } + break; + } + case RE_OP_END_LOOKAROUND: /* End of a lookaround subpattern. */ + { + BOOL has_groups; + TRACE(("%s\n", re_op_text[op])) + + /* sstack: - + * + * bstack: [captures TRUE | FALSE] fuzzy_counts capture_change + * + * pstack: - + */ + + if (!pop_size(state, &state->bstack, &state->capture_change)) + return RE_ERROR_MEMORY; + if (!pop_fuzzy_counts(state, &state->bstack, state->fuzzy_counts)) + return RE_ERROR_MEMORY; + if (!pop_bool(state, &state->bstack, &has_groups)) + return RE_ERROR_MEMORY; + if (has_groups) { + if (!pop_captures(state, &state->bstack)) + return RE_ERROR_MEMORY; + } + + /* sstack: - + * + * bstack: - + * + * pstack: - + */ + break; + } + case RE_OP_FAILURE: /* Failure. */ + TRACE(("%s\n", re_op_text[op])) + + /* Have we been looking for a POSIX match? */ + if (state->found_match) { + restore_best_match(state); + return RE_OP_SUCCESS; + } + + /* Do we have to advance? */ + if (!search) + return RE_ERROR_FAILURE; + + /* Can we advance? */ + state->text_pos = state->match_pos; + + if (state->reverse) { + if (state->text_pos <= state->slice_start) + return RE_ERROR_FAILURE; + } else { + if (state->text_pos >= state->slice_end) + return RE_ERROR_FAILURE; + } + + /* Skip over any repeated leading characters. */ + switch (start_node->op) { + case RE_OP_GREEDY_REPEAT_ONE: + case RE_OP_LAZY_REPEAT_ONE: + { + size_t count; + BOOL is_partial; + + /* How many characters did the repeat actually match? */ + count = count_one(state, start_node->nonstring.next_2.node, + state->text_pos, start_node->values[2], &is_partial); + + /* If it's fewer than the maximum then skip over those + * characters. + */ + if (count < start_node->values[2]) + state->text_pos += (Py_ssize_t)count * pattern_step; + break; + } + } + + /* Advance and try to match again. We also need to check whether we + * need to skip. + */ + if (state->reverse) { + if (state->text_pos > state->slice_end) + state->text_pos = state->slice_end; + else + --state->text_pos; + } else { + if (state->text_pos < state->slice_start) + state->text_pos = state->slice_start; + else + ++state->text_pos; + } + + /* Clear the groups. */ + clear_groups(state); + + /* Reset the guards. */ + reset_guards(state); + + /* Reset the stacks. */ + ByteStack_reset(state, &state->sstack); + ByteStack_reset(state, &state->bstack); + ByteStack_reset(state, &state->pstack); + goto start_match; + case RE_OP_FUZZY: /* Fuzzy matching. */ + TRACE(("%s\n", re_op_text[op])) + + /* sstack: outer_counts outer_node + * + * bstack: - + */ + + /* Restore the outer fuzzy info. */ + if (!pop_pointer(state, &state->sstack, (void*)&state->fuzzy_node)) + return RE_ERROR_MEMORY; + if (!pop_fuzzy_counts(state, &state->sstack, state->fuzzy_counts)) + return RE_ERROR_MEMORY; + break; + case RE_OP_FUZZY_INSERT: + TRACE(("%s\n", re_op_text[op])) + + status = retry_fuzzy_insert(state, &node); + if (status < 0) + return status; + + if (status == RE_ERROR_SUCCESS) + goto advance; + + string_pos = -1; + break; + case RE_OP_GREEDY_REPEAT: /* Greedy repeat. */ + case RE_OP_LAZY_REPEAT: /* Lazy repeat. */ + { + RE_RepeatStateData data_r; + Py_ssize_t text_pos; + RE_CODE index; + size_t capture_change; + Py_ssize_t start; + size_t count; + RE_RepeatData* rp_data; + TRACE(("%s\n", re_op_text[op])) + + /* bstack: count start capture_change index text_pos */ + + if (!ByteStack_pop_block(state, &state->bstack, (void*)&data_r, + sizeof(data_r))) + return RE_ERROR_MEMORY; + + text_pos = data_r.text_pos; + index = data_r.index; + capture_change = data_r.capture_change; + start = data_r.start; + count = data_r.count; + + /* The repeat failed to match. */ + rp_data = &state->repeats[index]; + + /* The body may have failed to match at this position. */ + if (!guard_repeat(state, index, text_pos, RE_STATUS_BODY, TRUE)) + return RE_ERROR_MEMORY; + + /* Restore the previous repeat. */ + rp_data->count = count; + rp_data->start = start; + rp_data->capture_change = capture_change; + break; + } + case RE_OP_GREEDY_REPEAT_ONE: /* Greedy repeat for one character. */ + { + RE_RepeatOneStateData data_ro; + RE_CODE index; + Py_ssize_t start; + size_t saved_count; + RE_RepeatData* rp_data; + size_t count; + Py_ssize_t step; + Py_ssize_t pos; + Py_ssize_t limit; + RE_Node* test; + BOOL match; + BOOL m; + TRACE(("%s\n", re_op_text[op])) + + /* bstack: count start node index */ + + if (!ByteStack_pop_block(state, &state->bstack, + (void*)&data_ro,sizeof(data_ro))) + return RE_ERROR_MEMORY; + + index = data_ro.index; + node = data_ro.node; + start = data_ro.start; + saved_count = data_ro.count; + + rp_data = &state->repeats[index]; + + /* Unmatch one character at a time until the tail could match or we + * have reached the minimum. + */ + state->text_pos = rp_data->start; + + count = rp_data->count; + step = node->nonstring.next_2.test->step; + pos = state->text_pos + (Py_ssize_t)count * step; + limit = state->text_pos + (Py_ssize_t)node->values[1] * step; + + /* The tail failed to match at this position. */ + if (!guard_repeat(state, index, pos, RE_STATUS_TAIL, TRUE)) + return RE_ERROR_MEMORY; + + /* A (*SKIP) might have changed the size of the slice. */ + if (step > 0) { + if (limit < state->slice_start) + limit = state->slice_start; + } else { + if (limit > state->slice_end) + limit = state->slice_end; + } + + if (pos == limit) { + /* We've backtracked the repeat as far as we can. */ + rp_data->start = start; + rp_data->count = saved_count; + break; + } + + test = node->next_1.test; + + m = test->match; + index = node->values[0]; + + match = FALSE; + + if (test->status & RE_STATUS_FUZZY) { + for (;;) { + RE_Position next_position; + + pos -= step; + + status = try_match(state, &node->next_1, pos, + &next_position); + if (status < 0) + return status; + + if (status != RE_ERROR_FAILURE && !is_repeat_guarded(state, + index, pos, RE_STATUS_TAIL)) { + match = TRUE; + break; + } + + if (pos == limit) + break; + } + } else { + /* A repeated single-character match is often followed by a + * literal, so checking specially for it can be a good + * optimisation when working with long strings. + */ + switch (test->op) { + case RE_OP_CHARACTER: + { + Py_UCS4 ch; + + ch = test->values[0]; + + for (;;) { + --pos; + + if (same_char(char_at(state->text, pos), ch) == m && + !is_repeat_guarded(state, index, pos, + RE_STATUS_TAIL)) { + match = TRUE; + break; + } + + if (pos == limit) + break; + } + break; + } + case RE_OP_CHARACTER_IGN: + { + Py_UCS4 ch; + + ch = test->values[0]; + + for (;;) { + --pos; + + if (same_char_ign(encoding, locale_info, + char_at(state->text, pos), ch) == m && + !is_repeat_guarded(state, index, pos, + RE_STATUS_TAIL)) { + match = TRUE; + break; + } + + if (pos == limit) + break; + } + break; + } + case RE_OP_CHARACTER_IGN_REV: + { + Py_UCS4 ch; + + ch = test->values[0]; + + for (;;) { + ++pos; + + if (same_char_ign(encoding, locale_info, + char_at(state->text, pos - 1), ch) == m && + !is_repeat_guarded(state, index, pos, + RE_STATUS_TAIL)) { + match = TRUE; + break; + } + + if (pos == limit) + break; + } + break; + } + case RE_OP_CHARACTER_REV: + { + Py_UCS4 ch; + + ch = test->values[0]; + + for (;;) { + ++pos; + + if (same_char(char_at(state->text, pos - 1), ch) == m + && !is_repeat_guarded(state, index, pos, + RE_STATUS_TAIL)) { + match = TRUE; + break; + } + + if (pos == limit) + break; + } + break; + } + case RE_OP_STRING: + { + Py_ssize_t length; + + length = (Py_ssize_t)test->value_count; + + --pos; + + /* Is it a partial match? */ + if (pos >= limit && pos > state->slice_end - length && + state->partial_side == RE_PARTIAL_RIGHT) { + do { + if (partial_string_match(state, test, pos)) + return RE_ERROR_PARTIAL; + + --pos; + } while (pos >= limit && pos > state->slice_end - + length && state->partial_side == RE_PARTIAL_RIGHT); + } + + /* The tail is a string. We don't want to go off the end of + * the slice. + */ + pos = min_ssize_t(pos, state->slice_end - length); + + for (;;) { + Py_ssize_t found; + BOOL is_partial; + + if (pos < limit) + break; + + found = string_search_rev(state, test, pos + length, + limit, FALSE, &is_partial); + if (is_partial) + return RE_ERROR_PARTIAL; + + if (found < 0) + break; + + pos = found - length; + + if (!is_repeat_guarded(state, index, pos, + RE_STATUS_TAIL)) { + match = TRUE; + break; + } + + --pos; + } + break; + } + case RE_OP_STRING_FLD: + { + int (*full_case_fold)(RE_LocaleInfo* locale_info, Py_UCS4 + ch, Py_UCS4* folded); + Py_ssize_t folded_length; + size_t i; + Py_UCS4 folded[RE_MAX_FOLDED]; + + full_case_fold = encoding->full_case_fold; + + folded_length = 0; + for (i = 0; i < test->value_count; i++) + folded_length += full_case_fold(locale_info, + test->values[i], folded); + + /* The tail is a string. We don't want to go off the end of + * the slice. + */ + pos = min_ssize_t(pos - 1, state->slice_end - + folded_length); + + for (;;) { + Py_ssize_t found; + Py_ssize_t new_pos; + BOOL is_partial; + + if (pos < limit) + break; + + found = string_search_fld_rev(state, test, pos + + folded_length, limit, &new_pos, &is_partial); + if (is_partial) + return RE_ERROR_PARTIAL; + + if (found < 0) + break; + + pos = found - folded_length; + + if (!is_repeat_guarded(state, index, pos, + RE_STATUS_TAIL)) { + match = TRUE; + break; + } + + --pos; + } + break; + } + case RE_OP_STRING_FLD_REV: + { + int (*full_case_fold)(RE_LocaleInfo* locale_info, Py_UCS4 + ch, Py_UCS4* folded); + Py_ssize_t folded_length; + size_t i; + Py_UCS4 folded[RE_MAX_FOLDED]; + + full_case_fold = encoding->full_case_fold; + + folded_length = 0; + for (i = 0; i < test->value_count; i++) + folded_length += full_case_fold(locale_info, + test->values[i], folded); + + /* The tail is a string. We don't want to go off the end of + * the slice. + */ + pos = max_ssize_t(pos + 1, state->slice_start + + folded_length); + + for (;;) { + Py_ssize_t found; + Py_ssize_t new_pos; + BOOL is_partial; + + if (pos > limit) + break; + + found = string_search_fld(state, test, pos - + folded_length, limit, &new_pos, &is_partial); + if (is_partial) + return RE_ERROR_PARTIAL; + + if (found < 0) + break; + + pos = found + folded_length; + + if (!is_repeat_guarded(state, index, pos, + RE_STATUS_TAIL)) { + match = TRUE; + break; + } + + ++pos; + } + break; + } + case RE_OP_STRING_IGN: + { + Py_ssize_t length; + + length = (Py_ssize_t)test->value_count; + + --pos; + + /* Is it a partial match? */ + if (pos >= limit && pos > state->slice_end - length && + state->partial_side == RE_PARTIAL_RIGHT) { + do { + if (partial_string_match_ign(state, test, pos)) + return RE_ERROR_PARTIAL; + + --pos; + } while (pos >= limit && pos > state->slice_end - + length && state->partial_side == RE_PARTIAL_RIGHT); + } + + /* The tail is a string. We don't want to go off the end of + * the slice. + */ + pos = min_ssize_t(pos, state->slice_end - length); + + for (;;) { + Py_ssize_t found; + BOOL is_partial; + + if (pos < limit) + break; + + found = string_search_ign_rev(state, test, pos + + length, limit, FALSE, &is_partial); + if (is_partial) + return RE_ERROR_PARTIAL; + + if (found < 0) + break; + + pos = found - length; + + if (!is_repeat_guarded(state, index, pos, + RE_STATUS_TAIL)) { + match = TRUE; + break; + } + + --pos; + } + break; + } + case RE_OP_STRING_IGN_REV: + { + Py_ssize_t length; + + length = (Py_ssize_t)test->value_count; + + /* The tail is a string. We don't want to go off the end of + * the slice. + */ + pos = max_ssize_t(pos + 1, state->slice_start + length); + + for (;;) { + Py_ssize_t found; + BOOL is_partial; + + if (pos > limit) + break; + + found = string_search_ign(state, test, pos - length, + limit, FALSE, &is_partial); + if (is_partial) + return RE_ERROR_PARTIAL; + + if (found < 0) + break; + + pos = found + length; + + if (!is_repeat_guarded(state, index, pos, + RE_STATUS_TAIL)) { + match = TRUE; + break; + } + + ++pos; + } + break; + } + case RE_OP_STRING_REV: + { + Py_ssize_t length; + + length = (Py_ssize_t)test->value_count; + + /* The tail is a string. We don't want to go off the end of + * the slice. + */ + pos = max_ssize_t(pos + 1, state->slice_start + length); + + for (;;) { + Py_ssize_t found; + BOOL is_partial; + + if (pos > limit) + break; + + found = string_search(state, test, pos - length, limit, + FALSE, &is_partial); + if (is_partial) + return RE_ERROR_PARTIAL; + + if (found < 0) + break; + + pos = found + length; + + if (!is_repeat_guarded(state, index, pos, + RE_STATUS_TAIL)) { + match = TRUE; + break; + } + + ++pos; + } + break; + } + default: + for (;;) { + RE_Position next_position; + + pos -= step; + + status = try_match(state, &node->next_1, pos, + &next_position); + if (status < 0) + return status; + + if (status == RE_ERROR_SUCCESS && + !is_repeat_guarded(state, index, pos, + RE_STATUS_TAIL)) { + match = TRUE; + break; + } + + if (pos == limit) + break; + } + break; + } + } + + if (match) { + count = (size_t)abs_ssize_t(pos - state->text_pos); + + /* The tail could match. */ + if (count > node->values[1]) { + /* The match is longer than the minimum, so we might need + * to backtrack the repeat again to consume less. + */ + RE_RepeatOneStateData data_ro; + + rp_data->count = count; + + data_ro.count = saved_count; + data_ro.start = start; + data_ro.node = node; + data_ro.index = index; + + if (!ByteStack_push_block(state, &state->bstack, + (void*)&data_ro, sizeof(data_ro))) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, + RE_OP_GREEDY_REPEAT_ONE)) + return RE_ERROR_MEMORY; + + /* bstack: count start node index GREEDY_REPEAT_ONE */ + } else { + /* We've reached or passed the minimum, so we won't need to + * backtrack the repeat again. + */ + rp_data->start = start; + rp_data->count = saved_count; + + /* Have we passed the minimum? */ + if (count < node->values[1]) + goto backtrack; + } + + node = node->next_1.node; + state->text_pos = pos; + goto advance; + } else { + /* Don't try this repeated match again. */ + if (step > 0) { + if (!guard_repeat_range(state, index, limit, pos, + RE_STATUS_BODY, TRUE)) + return RE_ERROR_MEMORY; + } else if (step < 0) { + if (!guard_repeat_range(state, index, pos, limit, + RE_STATUS_BODY, TRUE)) + return RE_ERROR_MEMORY; + } + + /* We've backtracked the repeat as far as we can. */ + rp_data->start = start; + rp_data->count = saved_count; + } + break; + } + case RE_OP_GROUP_CALL: /* Group call. */ + { + TRACE(("%s\n", re_op_text[op])) + + /* sstack: caller_groups caller_repeats capture_change return_node + * + * bstack: - + */ + + if (!drop_pointer(state, &state->sstack)) + return RE_ERROR_MEMORY; + + /* For the caller. */ + if (!pop_size(state, &state->sstack, &state->capture_change)) + return RE_ERROR_MEMORY; + if (!pop_repeats(state, &state->sstack)) + return RE_ERROR_MEMORY; + if (!pop_groups(state, &state->sstack)) + return RE_ERROR_MEMORY; + break; + } + case RE_OP_GROUP_RETURN: /* Group return. */ + { + RE_Node* return_node; + TRACE(("%s\n", re_op_text[op])) + + /* If called: + * + * sstack: - + * + * bstack: callee_groups callee_repeats capture_change return_node + * + * else: + * + * sstack: - + * + * bstack: NULL + */ + + if (!pop_pointer(state, &state->bstack, (void*)&return_node)) + return RE_ERROR_MEMORY; + + if (return_node) { + /* For the caller. */ + if (!push_groups(state, &state->sstack)) + return RE_ERROR_MEMORY; + if (!push_repeats(state, &state->sstack)) + return RE_ERROR_MEMORY; + if (!push_size(state, &state->sstack, state->capture_change)) + return RE_ERROR_MEMORY; + if (!push_pointer(state, &state->sstack, return_node)) + return RE_ERROR_MEMORY; + + /* sstack: caller_groups caller_repeats capture_change + * return_node + * + * bstack: callee_groups callee_repeats capture_change + */ + + /* For the callee. */ + if (!pop_size(state, &state->bstack, &state->capture_change)) + return RE_ERROR_MEMORY; + if (!pop_repeats(state, &state->bstack)) + return RE_ERROR_MEMORY; + if (!pop_groups(state, &state->bstack)) + return RE_ERROR_MEMORY; + } else { + if (!push_pointer(state, &state->sstack, NULL)) + return RE_ERROR_MEMORY; + } + + /* If called: + * + * sstack: caller_groups caller_repeats capture_change return_node + * + * bstack: - + * + * else: + * + * sstack: NULL + * + * bstack: - + */ + break; + } + case RE_OP_KEEP: /* Keep. */ + /* bstack: match_pos */ + + if (!pop_ssize(state, &state->bstack, &state->match_pos)) + return RE_ERROR_MEMORY; + break; + case RE_OP_LAZY_REPEAT_ONE: /* Lazy repeat for one character. */ + { + RE_RepeatOneStateData data; + RE_CODE index; + Py_ssize_t start; + size_t saved_count; + RE_RepeatData* rp_data; + size_t count; + Py_ssize_t step; + Py_ssize_t pos; + Py_ssize_t available; + size_t max_count; + Py_ssize_t limit; + RE_Node* repeated; + RE_Node* test; + BOOL match; + Py_ssize_t skip_pos; + BOOL m; + TRACE(("%s\n", re_op_text[op])) + + /* bstack: count start node index */ + + if (!ByteStack_pop_block(state, &state->bstack, (void*)&data, + sizeof(data))) + return RE_ERROR_MEMORY; + + index = data.index; + node = data.node; + start = data.start; + saved_count = data.count; + + rp_data = &state->repeats[index]; + + /* Match one character at a time until the tail could match or we + * have reached the maximum. + */ + state->text_pos = rp_data->start; + count = rp_data->count; + + step = node->nonstring.next_2.test->step; + pos = state->text_pos + (Py_ssize_t)count * step; + available = step > 0 ? state->slice_end - state->text_pos : + state->text_pos - state->slice_start; + max_count = min_size_t((size_t)available, node->values[2]); + limit = state->text_pos + (Py_ssize_t)max_count * step; + + repeated = node->nonstring.next_2.node; + + test = node->next_1.test; + + m = test->match; + index = node->values[0]; + + match = FALSE; + skip_pos = -1; + if (test->status & RE_STATUS_FUZZY) { + for (;;) { + RE_Position next_position; + + status = match_one(state, repeated, pos); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + break; + + pos += step; + + status = try_match(state, &node->next_1, pos, + &next_position); + if (status < 0) + return status; + + if (status == RE_ERROR_SUCCESS && !is_repeat_guarded(state, + index, pos, RE_STATUS_TAIL)) { + match = TRUE; + break; + } + + if (pos == limit) + break; + } + } else { + /* A repeated single-character match is often followed by a + * literal, so checking specially for it can be a good + * optimisation when working with long strings. + */ + switch (test->op) { + case RE_OP_CHARACTER: + { + Py_UCS4 ch; + + ch = test->values[0]; + + /* The tail is a character. We don't want to go off the end + * of the slice. + */ + limit = min_ssize_t(limit, state->slice_end - 1); + + for (;;) { + if (pos + 1 >= state->text_end && + state->partial_side == RE_PARTIAL_RIGHT) + return RE_ERROR_PARTIAL; + + if (pos >= limit) + break; + + status = match_one(state, repeated, pos); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + break; + + ++pos; + + if (same_char(char_at(state->text, pos), ch) == m && + !is_repeat_guarded(state, index, pos, + RE_STATUS_TAIL)) { + match = TRUE; + break; + } + } + break; + } + case RE_OP_CHARACTER_IGN: + { + Py_UCS4 ch; + + ch = test->values[0]; + + /* The tail is a character. We don't want to go off the end + * of the slice. + */ + limit = min_ssize_t(limit, state->slice_end - 1); + + for (;;) { + if (pos + 1 >= state->text_end && + state->partial_side == RE_PARTIAL_RIGHT) + return RE_ERROR_PARTIAL; + + if (pos >= limit) + break; + + status = match_one(state, repeated, pos); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + break; + + ++pos; + + if (same_char_ign(encoding, locale_info, + char_at(state->text, pos), ch) == m && + !is_repeat_guarded(state, index, pos, + RE_STATUS_TAIL)) { + match = TRUE; + break; + } + } + break; + } + case RE_OP_CHARACTER_IGN_REV: + { + Py_UCS4 ch; + + ch = test->values[0]; + + /* The tail is a character. We don't want to go off the end + * of the slice. + */ + limit = max_ssize_t(limit, state->slice_start + 1); + + for (;;) { + if (pos - 1 <= state->text_start && state->partial_side == + RE_PARTIAL_LEFT) + return RE_ERROR_PARTIAL; + + if (pos <= limit) + break; + + status = match_one(state, repeated, pos); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + break; + + --pos; + + if (same_char_ign(encoding, locale_info, + char_at(state->text, pos - 1), ch) == m && + !is_repeat_guarded(state, index, pos, + RE_STATUS_TAIL)) { + match = TRUE; + break; + } + } + break; + } + case RE_OP_CHARACTER_REV: + { + Py_UCS4 ch; + + ch = test->values[0]; + + /* The tail is a character. We don't want to go off the end + * of the slice. + */ + limit = max_ssize_t(limit, state->slice_start + 1); + + for (;;) { + if (pos - 1 <= state->text_start && state->partial_side == + RE_PARTIAL_LEFT) + return RE_ERROR_PARTIAL; + + if (pos <= limit) + break; + + status = match_one(state, repeated, pos); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + break; + + --pos; + + if (same_char(char_at(state->text, pos - 1), ch) == m + && !is_repeat_guarded(state, index, pos, + RE_STATUS_TAIL)) { + match = TRUE; + break; + } + } + break; + } + case RE_OP_STRING: + { + Py_ssize_t length; + + length = (Py_ssize_t)test->value_count; + + /* The tail is a string. We don't want to go off the end of + * the slice. + */ + limit = min_ssize_t(limit, state->slice_end - length); + + for (;;) { + Py_ssize_t found; + BOOL is_partial; + + if (pos >= state->text_end && state->partial_side == + RE_PARTIAL_RIGHT) + return RE_ERROR_PARTIAL; + + /* Look for the tail string. */ + found = string_search(state, test, pos + 1, limit + + length, TRUE, &is_partial); + if (is_partial) + return RE_ERROR_PARTIAL; + + if (found < 0) + break; + + if (repeated->op == RE_OP_ANY_ALL) + /* Anything can precede the tail. */ + pos = found; + else { + /* Check that what precedes the tail will match. */ + while (pos != found) { + status = match_one(state, repeated, pos); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + break; + + ++pos; + } + + if (pos != found) + /* Something preceding the tail didn't match. + */ + break; + } + + if (!is_repeat_guarded(state, index, pos, + RE_STATUS_TAIL)) { + match = TRUE; + break; + } + } + break; + } + case RE_OP_STRING_FLD: + { + /* The tail is a string. We don't want to go off the end of + * the slice. + */ + limit = min_ssize_t(limit, state->slice_end); + + for (;;) { + Py_ssize_t found; + Py_ssize_t new_pos; + BOOL is_partial; + + if (pos >= state->text_end && state->partial_side == + RE_PARTIAL_RIGHT) + return RE_ERROR_PARTIAL; + + /* Look for the tail string. */ + found = string_search_fld(state, test, pos + 1, limit, + &new_pos, &is_partial); + if (is_partial) + return RE_ERROR_PARTIAL; + + if (found < 0) + break; + + if (repeated->op == RE_OP_ANY_ALL) + /* Anything can precede the tail. */ + pos = found; + else { + /* Check that what precedes the tail will match. */ + while (pos != found) { + status = match_one(state, repeated, pos); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + break; + + ++pos; + } + + if (pos != found) + /* Something preceding the tail didn't match. + */ + break; + } + + if (!is_repeat_guarded(state, index, pos, + RE_STATUS_TAIL)) { + match = TRUE; + skip_pos = new_pos; + break; + } + } + break; + } + case RE_OP_STRING_FLD_REV: + { + /* The tail is a string. We don't want to go off the end of + * the slice. + */ + limit = max_ssize_t(limit, state->slice_start); + + for (;;) { + Py_ssize_t found; + Py_ssize_t new_pos; + BOOL is_partial; + + if (pos <= state->text_start && state->partial_side == RE_PARTIAL_LEFT) + return RE_ERROR_PARTIAL; + + /* Look for the tail string. */ + found = string_search_fld_rev(state, test, pos - 1, + limit, &new_pos, &is_partial); + if (is_partial) + return RE_ERROR_PARTIAL; + + if (found < 0) + break; + + if (repeated->op == RE_OP_ANY_ALL) + /* Anything can precede the tail. */ + pos = found; + else { + /* Check that what precedes the tail will match. */ + while (pos != found) { + status = match_one(state, repeated, pos); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + break; + + --pos; + } + + if (pos != found) + /* Something preceding the tail didn't match. + */ + break; + } + + if (!is_repeat_guarded(state, index, pos, + RE_STATUS_TAIL)) { + match = TRUE; + skip_pos = new_pos; + break; + } + } + break; + } + case RE_OP_STRING_IGN: + { + Py_ssize_t length; + + length = (Py_ssize_t)test->value_count; + + /* The tail is a string. We don't want to go off the end of + * the slice. + */ + limit = min_ssize_t(limit, state->slice_end - length); + + for (;;) { + Py_ssize_t found; + BOOL is_partial; + + if (pos >= state->text_end && state->partial_side == + RE_PARTIAL_RIGHT) + return RE_ERROR_PARTIAL; + + /* Look for the tail string. */ + found = string_search_ign(state, test, pos + 1, limit + + length, TRUE, &is_partial); + if (is_partial) + return RE_ERROR_PARTIAL; + + if (found < 0) + break; + + if (repeated->op == RE_OP_ANY_ALL) + /* Anything can precede the tail. */ + pos = found; + else { + /* Check that what precedes the tail will match. */ + while (pos != found) { + status = match_one(state, repeated, pos); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + break; + + ++pos; + } + + if (pos != found) + /* Something preceding the tail didn't match. + */ + break; + } + + if (!is_repeat_guarded(state, index, pos, + RE_STATUS_TAIL)) { + match = TRUE; + break; + } + } + break; + } + case RE_OP_STRING_IGN_REV: + { + Py_ssize_t length; + + length = (Py_ssize_t)test->value_count; + + /* The tail is a string. We don't want to go off the end of + * the slice. + */ + limit = max_ssize_t(limit, state->slice_start + length); + + for (;;) { + Py_ssize_t found; + BOOL is_partial; + + if (pos <= state->text_start && state->partial_side == RE_PARTIAL_LEFT) + return RE_ERROR_PARTIAL; + + /* Look for the tail string. */ + found = string_search_ign_rev(state, test, pos - 1, + limit - length, TRUE, &is_partial); + if (is_partial) + return RE_ERROR_PARTIAL; + + if (found < 0) + break; + + if (repeated->op == RE_OP_ANY_ALL) + /* Anything can precede the tail. */ + pos = found; + else { + /* Check that what precedes the tail will match. */ + while (pos != found) { + status = match_one(state, repeated, pos); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + break; + + --pos; + } + + if (pos != found) + /* Something preceding the tail didn't match. + */ + break; + } + + if (!is_repeat_guarded(state, index, pos, + RE_STATUS_TAIL)) { + match = TRUE; + break; + } + } + break; + } + case RE_OP_STRING_REV: + { + Py_ssize_t length; + + length = (Py_ssize_t)test->value_count; + + /* The tail is a string. We don't want to go off the end of + * the slice. + */ + limit = max_ssize_t(limit, state->slice_start + length); + + for (;;) { + Py_ssize_t found; + BOOL is_partial; + + if (pos <= state->text_start && state->partial_side == RE_PARTIAL_LEFT) + return RE_ERROR_PARTIAL; + + /* Look for the tail string. */ + found = string_search_rev(state, test, pos - 1, limit - + length, TRUE, &is_partial); + if (is_partial) + return RE_ERROR_PARTIAL; + + if (found < 0) + break; + + if (repeated->op == RE_OP_ANY_ALL) + /* Anything can precede the tail. */ + pos = found; + else { + /* Check that what precedes the tail will match. */ + while (pos != found) { + status = match_one(state, repeated, pos); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + break; + + --pos; + } + + if (pos != found) + /* Something preceding the tail didn't match. + */ + break; + } + + if (!is_repeat_guarded(state, index, pos, + RE_STATUS_TAIL)) { + match = TRUE; + break; + } + } + break; + } + default: + for (;;) { + RE_Position next_position; + + status = match_one(state, repeated, pos); + if (status < 0) + return status; + + if (status == RE_ERROR_FAILURE) + break; + + pos += step; + + status = try_match(state, &node->next_1, pos, + &next_position); + if (status < 0) + return RE_ERROR_PARTIAL; + + if (status == RE_ERROR_SUCCESS && + !is_repeat_guarded(state, index, pos, + RE_STATUS_TAIL)) { + match = TRUE; + break; + } + + if (pos == limit) + break; + } + break; + } + } + + if (match) { + /* The tail could match. */ + count = (size_t)abs_ssize_t(pos - state->text_pos); + state->text_pos = pos; + + if (count < max_count) { + /* The match is shorter than the maximum, so we might need + * to backtrack the repeat again to consume more. + */ + RE_RepeatOneStateData data_ro; + + rp_data->count = count; + + data_ro.count = saved_count; + data_ro.start = start; + data_ro.node = node; + data_ro.index = index; + + if (!ByteStack_push_block(state, &state->bstack, + (void*)&data_ro, sizeof(data_ro))) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, + RE_OP_LAZY_REPEAT_ONE)) + return RE_ERROR_MEMORY; + + /* bstack: count start node index LAZY_REPEAT_ONE */ + } else { + /* We've reached or passed the maximum, so we won't need to + * backtrack the repeat again. + */ + rp_data->start = start; + rp_data->count = saved_count; + + /* Have we passed the maximum? */ + if (count > max_count) + goto backtrack; + } + + node = node->next_1.node; + + if (skip_pos >= 0) { + state->text_pos = skip_pos; + node = node->next_1.node; + } + + goto advance; + } else { + /* The tail couldn't match. */ + rp_data->start = start; + rp_data->count = saved_count; + } + break; + } + case RE_OP_LOOKAROUND: /* Lookaround subpattern. */ + { + RE_Node* lookaround; + RE_LookaroundStateData data_l; + BOOL has_groups; + TRACE(("%s\n", re_op_text[op])) + + /* sstack: node slice_start slice_end text_pos ... + * + * bstack: [captures TRUE | FALSE] fuzzy_counts capture_change + * sstack + * + * pstack: bstack + */ + + if (!drop_bstack(state)) + return RE_ERROR_MEMORY; + if (!pop_sstack(state)) + return RE_ERROR_MEMORY; + + /* sstack: node slice_start slice_end text_pos + * + * bstack: [captures TRUE | FALSE] fuzzy_counts capture_change + * + * pstack: - + */ + + if (!ByteStack_pop_block(state, &state->sstack, (void*)&data_l, + sizeof(data_l))) + return RE_ERROR_MEMORY; + + state->text_pos = data_l.text_pos; + state->slice_end = data_l.slice_end; + state->slice_start = data_l.slice_start; + lookaround = data_l.node; + + /* sstack: - + * + * bstack: [captures TRUE | FALSE] fuzzy_counts capture_change + * + * pstack: - + */ + + if (!pop_size(state, &state->bstack, &state->capture_change)) + return RE_ERROR_MEMORY; + if (!pop_fuzzy_counts(state, &state->bstack, state->fuzzy_counts)) + return RE_ERROR_MEMORY; + if (!pop_bool(state, &state->bstack, &has_groups)) + return RE_ERROR_MEMORY; + if (has_groups) { + if (!pop_captures(state, &state->bstack)) + return RE_ERROR_MEMORY; + } + + /* sstack: - + * + * bstack: - + * + * pstack: - + */ + + if (!lookaround->match) { + /* It's a negative lookaround that's failed. */ + node = lookaround->nonstring.next_2.node; + goto advance; + } + break; + } + case RE_OP_MATCH_BODY: + { + RE_MatchBodyTailStateData data_mbt; + RE_CODE index; + size_t capture_change; + Py_ssize_t start; + size_t count; + RE_Position position; + RE_RepeatData* rp_data; + + /* bstack: position count start capture_change index text_pos */ + + if (!ByteStack_pop_block(state, &state->bstack, (void*)&data_mbt, + sizeof(data_mbt))) + return RE_ERROR_MEMORY; + + index = data_mbt.index; + capture_change = data_mbt.capture_change; + start = data_mbt.start; + count = data_mbt.count; + position = data_mbt.position; + TRACE(("%s %u\n", re_op_text[op], (unsigned int)index)) + + /* We want to match the body. */ + rp_data = &state->repeats[index]; + + /* Restore the repeat info. */ + rp_data->count = count; + rp_data->start = start; + rp_data->capture_change = capture_change; + + /* Record backtracking info in case the body fails to match. */ + if (!push_code(state, &state->bstack, index)) + return RE_ERROR_MEMORY; + if (!push_ssize(state, &state->bstack, data_mbt.text_pos)) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, RE_OP_BODY_START)) + return RE_ERROR_MEMORY; + + /* bstack: index text_pos BODY_START */ + + /* Advance into the body. */ + node = position.node; + state->text_pos = position.text_pos; + goto advance; + } + case RE_OP_MATCH_TAIL: + { + RE_MatchBodyTailStateData data_mbt; + RE_CODE index; + size_t capture_change; + Py_ssize_t start; + size_t count; + RE_Position position; + RE_RepeatData* rp_data; + + /* bstack: position count start capture_change index text_pos */ + + if (!ByteStack_pop_block(state, &state->bstack, (void*)&data_mbt, + sizeof(data_mbt))) + return RE_ERROR_MEMORY; + + index = data_mbt.index; + capture_change = data_mbt.capture_change; + start = data_mbt.start; + count = data_mbt.count; + position = data_mbt.position; + TRACE(("%s %u\n", re_op_text[op], (unsigned int)index)) + + /* We want to match the tail. */ + rp_data = &state->repeats[index]; + + /* Restore the repeat info. */ + rp_data->count = count; + rp_data->start = start; + rp_data->capture_change = capture_change; + + /* Record backtracking info in case the tail fails to match. */ + if (!push_code(state, &state->bstack, index)) + return RE_ERROR_MEMORY; + if (!push_ssize(state, &state->bstack, data_mbt.text_pos)) + return RE_ERROR_MEMORY; + if (!push_uint8(state, &state->bstack, RE_OP_TAIL_START)) + return RE_ERROR_MEMORY; + + /* bstack: index text_pos TAIL_START */ + + /* Advance into the tail. */ + node = position.node; + state->text_pos = position.text_pos; + goto advance; + } + case RE_OP_REF_GROUP: /* Reference to a capture group. */ + case RE_OP_REF_GROUP_IGN: /* Reference to a capture group, ignoring case. */ + case RE_OP_REF_GROUP_IGN_REV: /* Reference to a capture group, backwards, ignoring case. */ + case RE_OP_REF_GROUP_REV: /* Reference to a capture group, backwards. */ + case RE_OP_STRING: /* A string. */ + case RE_OP_STRING_IGN: /* A string, ignoring case. */ + case RE_OP_STRING_IGN_REV: /* A string, backwards, ignoring case. */ + case RE_OP_STRING_REV: /* A string, backwards. */ + { + TRACE(("%s\n", re_op_text[op])) + + status = retry_fuzzy_match_string(state, op, search, &node, + &string_pos); + if (status < 0) + return status; + + if (status == RE_ERROR_SUCCESS) + goto advance; + + string_pos = -1; + break; + } + case RE_OP_REF_GROUP_FLD: /* Reference to a capture group, ignoring case. */ + case RE_OP_REF_GROUP_FLD_REV: /* Reference to a capture group, backwards, ignoring case. */ + { + TRACE(("%s\n", re_op_text[op])) + + status = retry_fuzzy_match_group_fld(state, op, search, &node, + &folded_pos, &string_pos, &gfolded_pos); + if (status < 0) + return status; + + if (status == RE_ERROR_SUCCESS) + goto advance; + + string_pos = -1; + break; + } + case RE_OP_START_GROUP: /* Start of a capture group. */ + { + BOOL capture; + TRACE(("%s\n", re_op_text[op])) + + /* If capturing: + * + * sstack: - + * + * bstack: end current capture_change private_index public_index + * TRUE + * + * else: + * + * sstack: start + * + * bstack: FALSE + */ + + if (!pop_bool(state, &state->bstack, &capture)) + return RE_ERROR_MEMORY; + + if (capture) { + RE_GroupStateData data_g; + RE_CODE public_index; + RE_CODE private_index; + Py_ssize_t end; + RE_GroupData* group; + + if (!ByteStack_pop_block(state, &state->bstack, (void*)&data_g, + sizeof(data_g))) + return RE_ERROR_MEMORY; + + public_index = data_g.public_index; + private_index = data_g.private_index; + state->capture_change = data_g.capture_change; + group = &state->groups[private_index - 1]; + group->current = data_g.current; + end = data_g.text_pos; + if (!push_ssize(state, &state->sstack, end)) + return RE_ERROR_MEMORY; + + unsave_capture(state, private_index, public_index); + + /* sstack: end + * + * bstack: - + */ + } else { + if (!drop_ssize(state, &state->sstack)) + return RE_ERROR_MEMORY; + } + break; + } + case RE_OP_STRING_FLD: /* A string, ignoring case. */ + case RE_OP_STRING_FLD_REV: /* A string, backwards, ignoring case. */ + { + TRACE(("%s\n", re_op_text[op])) + + status = retry_fuzzy_match_string_fld(state, op, search, &node, + &string_pos, &folded_pos); + if (status < 0) + return status; + + if (status == RE_ERROR_SUCCESS) + goto advance; + + string_pos = -1; + break; + } + case RE_OP_TAIL_START: + { + Py_ssize_t text_pos; + RE_CODE index; + + /* bstack: index text_pos */ + + if (!pop_ssize(state, &state->bstack, &text_pos)) + return RE_ERROR_MEMORY; + if (!pop_code(state, &state->bstack, &index)) + return RE_ERROR_MEMORY; + TRACE(("%s %u\n", re_op_text[op], (unsigned int)index)) + + /* The tail may have failed to match at this position. */ + if (!guard_repeat(state, index, text_pos, RE_STATUS_TAIL, TRUE)) + return RE_ERROR_MEMORY; + break; + } + default: + TRACE(("UNKNOWN OP %d\n", op)) + return RE_ERROR_ILLEGAL; + } + } +} + +/* Saves group data for fuzzy matching. */ +Py_LOCAL_INLINE(RE_GroupData*) save_captures(RE_State* state, RE_GroupData* + saved_groups) { + PatternObject* pattern; + size_t g; + + /* Re-acquire the GIL. */ + acquire_GIL(state); + + pattern = state->pattern; + + if (!saved_groups) { + saved_groups = (RE_GroupData*)re_alloc(pattern->true_group_count * + sizeof(RE_GroupData)); + if (!saved_groups) + goto error; + + memset(saved_groups, 0, pattern->true_group_count * + sizeof(RE_GroupData)); + } + + for (g = 0; g < pattern->true_group_count; g++) { + RE_GroupData* orig; + RE_GroupData* copy; + + orig = &state->groups[g]; + copy = &saved_groups[g]; + + if (orig->count > copy->capacity) { + RE_GroupSpan* cap_copy; + + cap_copy = (RE_GroupSpan*)re_realloc(copy->captures, orig->count * + sizeof(RE_GroupSpan)); + if (!cap_copy) + goto error; + + copy->capacity = orig->count; + copy->captures = cap_copy; + } + + copy->count = orig->count; + Py_MEMCPY(copy->captures, orig->captures, orig->count * + sizeof(RE_GroupSpan)); + copy->current = orig->current; + } + + /* Release the GIL. */ + release_GIL(state); + + return saved_groups; + +error: + if (saved_groups) { + for (g = 0; g < pattern->true_group_count; g++) + re_dealloc(saved_groups[g].captures); + + re_dealloc(saved_groups); + } + + /* Release the GIL. */ + release_GIL(state); + + return NULL; +} + +/* Restores group data for fuzzy matching. */ +Py_LOCAL_INLINE(void) restore_groups(RE_State* state, RE_GroupData* + saved_groups) { + PatternObject* pattern; + size_t g; + + /* Re-acquire the GIL. */ + acquire_GIL(state); + + pattern = state->pattern; + + for (g = 0; g < pattern->true_group_count; g++) { + RE_GroupData* group; + RE_GroupData* saved; + + group = &state->groups[g]; + saved = &saved_groups[g]; + + group->count = saved->count; + Py_MEMCPY(group->captures, saved->captures, saved->count * + sizeof(RE_GroupSpan)); + group->current = saved->current; + + re_dealloc(saved->captures); + } + + re_dealloc(saved_groups); + + /* Release the GIL. */ + release_GIL(state); +} + +/* Discards group data for fuzzy matching. */ +Py_LOCAL_INLINE(void) discard_groups(RE_State* state, RE_GroupData* + saved_groups) { + PatternObject* pattern; + size_t g; + + /* Re-acquire the GIL. */ + acquire_GIL(state); + + pattern = state->pattern; + + for (g = 0; g < pattern->true_group_count; g++) + re_dealloc(saved_groups[g].captures); + + re_dealloc(saved_groups); + + /* Release the GIL. */ + release_GIL(state); +} + +/* Saves the fuzzy counts. */ +Py_LOCAL_INLINE(void) save_fuzzy_counts(RE_State* state, size_t* fuzzy_counts) + { + Py_MEMCPY(fuzzy_counts, state->fuzzy_counts, sizeof(state->fuzzy_counts)); +} + +/* Restores the fuzzy counts. */ +Py_LOCAL_INLINE(void) restore_fuzzy_counts(RE_State* state, size_t* + fuzzy_counts) { + Py_MEMCPY(state->fuzzy_counts, fuzzy_counts, sizeof(state->fuzzy_counts)); +} + +/* Initialises the list of best matches found so far. */ +Py_LOCAL_INLINE(void) init_best_list(RE_BestList* best_list) { + best_list->capacity = 0; + best_list->count = 0; + best_list->entries = NULL; +} + +/* Finalises the list of best matches found so far. */ +Py_LOCAL_INLINE(void) fini_best_list(RE_State* state, RE_BestList* best_list) { + safe_dealloc(state, best_list->entries); + best_list->capacity = 0; + best_list->count = 0; + best_list->entries = NULL; +} + +/* Clears the list of best matches found so far. */ +Py_LOCAL_INLINE(void) clear_best_list(RE_BestList* best_list) { + best_list->count = 0; +} + +/* Adds a new entry to the list of best matches found so far. */ +Py_LOCAL_INLINE(BOOL) add_to_best_list(RE_State* state, RE_BestList* best_list, + Py_ssize_t match_pos, Py_ssize_t text_pos) { + RE_BestEntry* entry; + + if (best_list->count >= best_list->capacity) { + size_t new_capacity; + RE_BestEntry* new_entries; + + new_capacity = best_list->capacity * 2; + + if (new_capacity == 0) + new_capacity = 16; + + new_entries = safe_realloc(state, best_list->entries, new_capacity * + sizeof(RE_BestEntry)); + if (!new_entries) + return FALSE; + + best_list->entries = new_entries; + best_list->capacity = new_capacity; + } + + entry = &best_list->entries[best_list->count++]; + entry->match_pos = match_pos; + entry->text_pos = text_pos; + + return TRUE; +} + +/* Performs a match or search from the current text position for a best fuzzy + * match. + */ +Py_LOCAL_INLINE(int) do_best_fuzzy_match(RE_State* state, BOOL search) { + Py_ssize_t available; + int step; + size_t fewest_errors; + BOOL must_advance; + BOOL found_match; + RE_BestList best_list; + RE_BestChangesList best_changes_list; + Py_ssize_t start_pos; + int status = RE_ERROR_FAILURE; + TRACE(("<>\n")) + + if (state->reverse) { + available = state->text_pos - state->slice_start; + step = -1; + } else { + available = state->slice_end - state->text_pos; + step = 1; + } + + /* The maximum permitted cost. */ + state->max_errors = PY_SSIZE_T_MAX; + fewest_errors = PY_SSIZE_T_MAX; + + state->best_text_pos = state->reverse ? state->slice_start : + state->slice_end; + + must_advance = state->must_advance; + found_match = FALSE; + + init_best_list(&best_list); + init_best_changes_list(&best_changes_list); + + /* Search the text for the best match. */ + start_pos = state->text_pos; + while (state->slice_start <= start_pos && start_pos <= state->slice_end) { + state->text_pos = start_pos; + state->must_advance = must_advance; + + /* Initialise the state. */ + init_match(state); + + status = RE_ERROR_SUCCESS; + if (state->max_errors == 0 && state->partial_side == RE_PARTIAL_NONE) { + /* An exact match, and partial matches not permitted. */ + if (available < state->min_width || (available == 0 && + state->must_advance)) + status = RE_ERROR_FAILURE; + } + + if (status == RE_ERROR_SUCCESS) + status = basic_match(state, search); + + /* Has an error occurred, or is it a partial match? */ + if (status < 0) + goto error; + + if (status == RE_ERROR_FAILURE) + break; + + /* It was a successful match. */ + found_match = TRUE; + + if (state->total_errors < fewest_errors) { + /* This match was better than any of the previous ones. */ + fewest_errors = state->total_errors; + + if (state->total_errors == 0) + /* It was a perfect match. */ + break; + + /* Forget all the previous worse matches and remember this one. */ + clear_best_list(&best_list); + if (!add_to_best_list(state, &best_list, state->match_pos, + state->text_pos)) + goto mem_error; + + clear_best_fuzzy_changes(state, &best_changes_list); + if (!add_best_fuzzy_changes(state, &best_changes_list)) + goto mem_error; + } else if (state->total_errors == fewest_errors) { + /* This match was as good as the previous matches. Remember this + * one. + */ + add_to_best_list(state, &best_list, state->match_pos, + state->text_pos); + if (!add_best_fuzzy_changes(state, &best_changes_list)) + goto mem_error; + } + + start_pos = state->match_pos; + state->max_errors = fewest_errors - 1; + } + + if (found_match) { + RE_FuzzyChangesList* list; + + /* We found a match. */ + if (fewest_errors > 0) { + /* It doesn't look like a perfect match. */ + size_t i; + Py_ssize_t slice_start; + Py_ssize_t slice_end; + size_t error_limit; + size_t best_fuzzy_counts[RE_FUZZY_COUNT]; + RE_FuzzyChangesList best_fuzzy_changes; + RE_GroupData* best_groups; + Py_ssize_t best_match_pos = 0; + Py_ssize_t best_text_pos; + + slice_start = state->slice_start; + slice_end = state->slice_end; + + error_limit = fewest_errors; + + if (error_limit > RE_MAX_ERRORS) + error_limit = RE_MAX_ERRORS; + + best_groups = NULL; + init_fuzzy_changes_list(&best_fuzzy_changes); + + /* Look again at the best of the matches that we've seen. */ + for (i = 0; i < best_list.count; i++) { + RE_BestEntry* entry; + Py_ssize_t max_offset; + Py_ssize_t offset; + + /* Look for the best fit at this position. */ + entry = &best_list.entries[i]; + + if (search) { + max_offset = state->reverse ? entry->match_pos - + state->slice_start : state->slice_end - entry->match_pos; + + if (max_offset > (Py_ssize_t)fewest_errors) + max_offset = (Py_ssize_t)fewest_errors; + + if (max_offset > (Py_ssize_t)error_limit) + max_offset = (Py_ssize_t)error_limit; + } else + max_offset = 0; + + start_pos = entry->match_pos; + offset = 0; + + while (offset <= max_offset) { + state->max_errors = 1; + + while (state->max_errors <= error_limit) { + state->text_pos = start_pos; + init_match(state); + status = basic_match(state, FALSE); + + if (status < 0) + goto error; + + if (status == RE_ERROR_SUCCESS) { + BOOL better = FALSE; + + if (state->total_errors < error_limit || (i == 0 && + offset == 0)) + better = TRUE; + else if (state->total_errors == error_limit) + /* The cost is as low as the current best, but + * is it earlier? + */ + better = state->reverse ? state->match_pos > + best_match_pos : state->match_pos < + best_match_pos; + + if (better) { + save_fuzzy_counts(state, best_fuzzy_counts); + if (!save_fuzzy_changes(state, + &best_fuzzy_changes)) + goto mem_error; + + best_groups = save_captures(state, + best_groups); + if (!best_groups) + goto mem_error; + + best_match_pos = state->match_pos; + best_text_pos = state->text_pos; + error_limit = state->total_errors; + } + + break; + } + + ++state->max_errors; + } + + start_pos += step; + ++offset; + } + + if (status == RE_ERROR_SUCCESS && state->total_errors == 0) + break; + } + + if (best_groups) { + status = RE_ERROR_SUCCESS; + state->match_pos = best_match_pos; + state->text_pos = best_text_pos; + + restore_groups(state, best_groups); + restore_fuzzy_counts(state, best_fuzzy_counts); + restore_fuzzy_changes(state, &best_fuzzy_changes); + } else { + /* None of the "best" matches could be improved on, so pick the + * first. + */ + RE_BestEntry* entry; + + /* Look at only the part of the string around the match. */ + entry = &best_list.entries[0]; + + if (state->reverse) { + state->slice_start = entry->text_pos; + state->slice_end = entry->match_pos; + } else { + state->slice_start = entry->match_pos; + state->slice_end = entry->text_pos; + } + + /* We'll expand the part that we're looking at to take to + * compensate for any matching errors that have occurred. + */ + if (state->slice_start - slice_start >= + (Py_ssize_t)fewest_errors) + state->slice_start -= (Py_ssize_t)fewest_errors; + else + state->slice_start = slice_start; + + if (slice_end - state->slice_end >= (Py_ssize_t)fewest_errors) + state->slice_end += (Py_ssize_t)fewest_errors; + else + state->slice_end = slice_end; + + state->max_errors = fewest_errors; + state->text_pos = entry->match_pos; + init_match(state); + status = basic_match(state, search); + + if (status < 0) + goto error; + + list = &best_changes_list.lists[0]; + state->fuzzy_changes.count = list->count; + Py_MEMCPY(state->fuzzy_changes.items, list->items, + (size_t)list->count * sizeof(RE_FuzzyChange)); + } + + fini_fuzzy_changes_list(state, &best_fuzzy_changes); + + state->slice_start = slice_start; + state->slice_end = slice_end; + } else + state->fuzzy_changes.count = 0; + } + + fini_best_list(state, &best_list); + fini_best_changes_list(state, &best_changes_list); + + return status; + +mem_error: + status = RE_ERROR_MEMORY; + +error: + fini_best_list(state, &best_list); + fini_best_changes_list(state, &best_changes_list); + return status; +} + +/* Performs a match or search from the current text position for an enhanced + * fuzzy match. + */ +Py_LOCAL_INLINE(int) do_enhanced_fuzzy_match(RE_State* state, BOOL search) { + PatternObject* pattern; + Py_ssize_t available; + size_t fewest_errors; + RE_GroupData* best_groups; + Py_ssize_t best_match_pos; + BOOL must_advance; + Py_ssize_t slice_start; + Py_ssize_t slice_end; + int status; + size_t best_fuzzy_counts[RE_FUZZY_COUNT]; + RE_FuzzyChangesList best_fuzzy_changes; + Py_ssize_t best_text_pos = 0; /* Initialise to stop compiler warning. */ + TRACE(("<>\n")) + + pattern = state->pattern; + + init_fuzzy_changes_list(&best_fuzzy_changes); + + if (state->reverse) + available = state->text_pos - state->slice_start; + else + available = state->slice_end - state->text_pos; + + /* The maximum permitted cost. */ + state->max_errors = PY_SSIZE_T_MAX; + fewest_errors = PY_SSIZE_T_MAX; + + best_groups = NULL; + + state->best_match_pos = state->text_pos; + state->best_text_pos = state->reverse ? state->slice_start : + state->slice_end; + + best_match_pos = state->text_pos; + must_advance = state->must_advance; + + slice_start = state->slice_start; + slice_end = state->slice_end; + + for (;;) { + /* If there's a better match, it won't start earlier in the string than + * the current best match, so there's no need to start earlier than + * that match. + */ + state->must_advance = must_advance; + + /* Initialise the state. */ + init_match(state); + + status = RE_ERROR_SUCCESS; + if (state->max_errors == 0 && state->partial_side == RE_PARTIAL_NONE) { + /* An exact match, and partial matches not permitted. */ + if (available < state->min_width || (available == 0 && + state->must_advance)) + status = RE_ERROR_FAILURE; + } + + if (status == RE_ERROR_SUCCESS) + status = basic_match(state, search); + + /* Has an error occurred, or is it a partial match? */ + if (status < 0) + break; + + if (status == RE_ERROR_SUCCESS) { + BOOL better; + + better = state->total_errors < fewest_errors; + + if (better) { + BOOL same_match; + + fewest_errors = state->total_errors; + state->max_errors = fewest_errors; + + save_fuzzy_counts(state, best_fuzzy_counts); + if (!save_fuzzy_changes(state, &best_fuzzy_changes)) + goto error; + + same_match = state->match_pos == best_match_pos && + state->text_pos == best_text_pos; + same_match = FALSE; + + if (best_groups) { + size_t g; + + /* Did we get the same match as the best so far? */ + for (g = 0; same_match && g < pattern->public_group_count; + g++) + same_match = same_span_of_group(&state->groups[g], + &best_groups[g]); + } + + /* Save the best result so far. */ + best_groups = save_captures(state, best_groups); + if (!best_groups) { + status = RE_ERROR_MEMORY; + break; + } + + best_match_pos = state->match_pos; + best_text_pos = state->text_pos; + + if (same_match || state->total_errors == 0) + break; + + state->max_errors = state->total_errors; + if (state->max_errors < RE_MAX_ERRORS) + --state->max_errors; + } else + break; + + if (state->reverse) { + state->slice_start = state->text_pos; + state->slice_end = state->match_pos; + } else { + state->slice_start = state->match_pos; + state->slice_end = state->text_pos; + } + + state->text_pos = state->match_pos; + + if (state->max_errors == PY_SSIZE_T_MAX) + state->max_errors = 0; + } else + break; + } + + if (status < 0 && status != RE_ERROR_PARTIAL) + goto error; + + state->slice_start = slice_start; + state->slice_end = slice_end; + + if (best_groups) { + if (status == RE_ERROR_SUCCESS && state->total_errors == 0) + /* We have a perfect match, so the previous best match. */ + discard_groups(state, best_groups); + else { + /* Restore the previous best match. */ + status = RE_ERROR_SUCCESS; + + state->match_pos = best_match_pos; + state->text_pos = best_text_pos; + + restore_groups(state, best_groups); + restore_fuzzy_counts(state, best_fuzzy_counts); + } + + restore_fuzzy_changes(state, &best_fuzzy_changes); + } + + fini_fuzzy_changes_list(state, &best_fuzzy_changes); + + return status; + +error: + fini_fuzzy_changes_list(state, &best_fuzzy_changes); + return status; +} + +/* Performs a match or search from the current text position for a simple fuzzy + * match. + */ +Py_LOCAL_INLINE(int) do_simple_fuzzy_match(RE_State* state, BOOL search) { + Py_ssize_t available; + int status; + TRACE(("<>\n")) + + if (state->reverse) + available = state->text_pos - state->slice_start; + else + available = state->slice_end - state->text_pos; + + /* The maximum permitted cost. */ + state->max_errors = PY_SSIZE_T_MAX; + + state->best_match_pos = state->text_pos; + state->best_text_pos = state->reverse ? state->slice_start : + state->slice_end; + + /* Initialise the state. */ + init_match(state); + + status = RE_ERROR_SUCCESS; + if (state->max_errors == 0 && state->partial_side == RE_PARTIAL_NONE) { + /* An exact match, and partial matches not permitted. */ + if (available < state->min_width || (available == 0 && + state->must_advance)) + status = RE_ERROR_FAILURE; + } + + if (status == RE_ERROR_SUCCESS) + status = basic_match(state, search); + + return status; +} + +/* Performs a match or search from the current text position for an exact + * match. + */ +Py_LOCAL_INLINE(int) do_exact_match(RE_State* state, BOOL search) { + Py_ssize_t available; + int status; + TRACE(("<>\n")) + + if (state->reverse) + available = state->text_pos - state->slice_start; + else + available = state->slice_end - state->text_pos; + + /* The maximum permitted cost. */ + state->max_errors = 0; + + state->best_match_pos = state->text_pos; + state->best_text_pos = state->reverse ? state->slice_start : + state->slice_end; + + /* Initialise the state. */ + init_match(state); + + status = RE_ERROR_SUCCESS; + if (state->max_errors == 0 && state->partial_side == RE_PARTIAL_NONE) { + /* An exact match, and partial matches not permitted. */ + if (available < state->min_width || (available == 0 && + state->must_advance)) + status = RE_ERROR_FAILURE; + } + + if (status == RE_ERROR_SUCCESS) + status = basic_match(state, search); + + return status; +} + +/* Performs the requested kind (i.e. fuzziness) of match. */ +Py_LOCAL_INLINE(int) do_match_2(RE_State* state, BOOL search) { + PatternObject* pattern; + + pattern = state->pattern; + + if (!pattern->is_fuzzy) + return do_exact_match(state, search); + + if (pattern->flags & RE_FLAG_BESTMATCH) + return do_best_fuzzy_match(state, search); + + if (pattern->flags & RE_FLAG_ENHANCEMATCH) + return do_enhanced_fuzzy_match(state, search); + + return do_simple_fuzzy_match(state, search); +} + +/* Performs a match or search from the current text position. + * + * The state can sometimes be shared across threads. In such instances there's + * a lock (mutex) on it. The lock is held for the duration of matching. + */ +Py_LOCAL_INLINE(int) do_match(RE_State* state, BOOL search) { + PatternObject* pattern; + int status; + TRACE(("<>\n")) + + pattern = state->pattern; + + /* Is there enough to search? */ + if (state->reverse) { + if (state->text_pos < state->slice_start) + return FALSE; + } else { + if (state->text_pos > state->slice_end) + return FALSE; + } + + /* Release the GIL. */ + release_GIL(state); + + /* Perform a normal match, but fall back to a partial match if requested. + */ + if (state->partial_side == RE_PARTIAL_NONE) + /* Normal match. */ + status = do_match_2(state, search); + else { + int partial_side; + Py_ssize_t text_pos; + + partial_side = state->partial_side; + text_pos = state->text_pos; + + /* Try a normal match first. */ + state->partial_side = RE_PARTIAL_NONE; + + status = do_match_2(state, search); + + state->partial_side = partial_side; + + if (status == RE_ERROR_FAILURE) { + /* Fall back to the partial match as originally requested. */ + state->text_pos = text_pos; + status = do_match_2(state, search); + } + } + + if (status == RE_ERROR_SUCCESS || status == RE_ERROR_PARTIAL) { + Py_ssize_t max_end_index; + RE_GroupInfo* group_info; + size_t g; + + /* Store the results. */ + state->lastindex = -1; + state->lastgroup = -1; + max_end_index = -1; + + if (status == RE_ERROR_PARTIAL) { + /* We've matched up to the limit of the slice. */ + if (state->reverse) + state->text_pos = state->slice_start; + else + state->text_pos = state->slice_end; + } + + /* Store the capture groups. */ + group_info = pattern->group_info; + + for (g = 0; g < pattern->public_group_count; g++) { + RE_GroupData* group; + + group = &state->groups[g]; + + if (group->current >= 0 && group_info[g].end_index > max_end_index) + { + max_end_index = group_info[g].end_index; + state->lastindex = (Py_ssize_t)g + 1; + if (group_info[g].has_name) + state->lastgroup = (Py_ssize_t)g + 1; + } + } + } + + /* Re-acquire the GIL. */ + acquire_GIL(state); + + if (status < 0 && status != RE_ERROR_PARTIAL && !PyErr_Occurred()) + set_error(status, NULL); + + return status; +} + +/* Gets a string from a Python object. + * + * If the function returns true and str_info->should_release is true then it's + * the responsibility of the caller to release the buffer when it's no longer + * needed. + */ +Py_LOCAL_INLINE(BOOL) get_string(PyObject* string, RE_StringInfo* str_info) { + /* Given a Python object, return a data pointer, a length (in characters), + * and a character size. Return FALSE if the object is not a string (or not + * compatible). + */ + /* Unicode objects do not support the buffer API. So, get the data directly + * instead. + */ + if (PyUnicode_Check(string)) { + /* Unicode strings don't always support the buffer interface. */ + if (PyUnicode_READY(string) == -1) + return FALSE; + + str_info->characters = (void*)PyUnicode_DATA(string); + str_info->length = PyUnicode_GET_LENGTH(string); + str_info->charsize = PyUnicode_KIND(string); + str_info->is_unicode = TRUE; + str_info->should_release = FALSE; + return TRUE; + } + + /* Get pointer to string buffer. */ + if (PyObject_GetBuffer(string, &str_info->view, PyBUF_SIMPLE) != 0) { + PyErr_SetString(PyExc_TypeError, "expected string or buffer"); + return FALSE; + } + + if (!str_info->view.buf) { + PyBuffer_Release(&str_info->view); + PyErr_SetString(PyExc_ValueError, "buffer is NULL"); + return FALSE; + } + + str_info->should_release = TRUE; + + str_info->characters = str_info->view.buf; + str_info->length = str_info->view.len; + str_info->charsize = 1; + str_info->is_unicode = FALSE; + + return TRUE; +} + +/* Deallocates the groups storage. */ +Py_LOCAL_INLINE(void) dealloc_groups(RE_GroupData* groups, size_t group_count) + { + size_t g; + + if (!groups) + return; + + for (g = 0; g < group_count; g++) + re_dealloc(groups[g].captures); + + re_dealloc(groups); +} + +/* Initialises a state object. */ +Py_LOCAL_INLINE(BOOL) state_init_2(RE_State* state, PatternObject* pattern, + PyObject* string, RE_StringInfo* str_info, Py_ssize_t start, Py_ssize_t end, + BOOL overlapped, int concurrent, BOOL partial, BOOL use_lock, BOOL + visible_captures, BOOL match_all, Py_ssize_t timeout) { + Py_ssize_t final_pos; + int p; + + state->thread_state = NULL; + + ByteStack_init(state, &state->sstack); + ByteStack_init(state, &state->bstack); + ByteStack_init(state, &state->pstack); + + /* We might already have some cached storage we can use for bstack. */ + if (pattern->stack_storage) { + state->bstack.storage = pattern->stack_storage; + state->bstack.capacity = pattern->stack_capacity; + pattern->stack_storage = NULL; + pattern->stack_capacity = 0; + } + + state->groups = NULL; + state->best_match_groups = NULL; + state->repeats = NULL; + state->visible_captures = visible_captures; + state->match_all = match_all; + state->lock = NULL; + state->fuzzy_guards = NULL; + state->group_call_guard_list = NULL; + state->req_pos = -1; + state->is_fuzzy = pattern->is_fuzzy; + + /* The call guards used by recursive patterns. */ + if (pattern->call_ref_info_count > 0) { + state->group_call_guard_list = + (RE_GuardList*)re_alloc(pattern->call_ref_info_count * + sizeof(RE_GuardList)); + if (!state->group_call_guard_list) + goto error; + memset(state->group_call_guard_list, 0, pattern->call_ref_info_count * + sizeof(RE_GuardList)); + } + + /* The capture groups. */ + if (pattern->true_group_count) { + size_t g; + + if (pattern->groups_storage) { + state->groups = pattern->groups_storage; + pattern->groups_storage = NULL; + } else { + state->groups = (RE_GroupData*)re_alloc(pattern->true_group_count * + sizeof(RE_GroupData)); + if (!state->groups) + goto error; + memset(state->groups, 0, pattern->true_group_count * + sizeof(RE_GroupData)); + + for (g = 0; g < pattern->true_group_count; g++) { + RE_GroupSpan* captures; + + captures = (RE_GroupSpan*)re_alloc(sizeof(RE_GroupSpan)); + if (!captures) { + size_t i; + + for (i = 0; i < g; i++) + re_dealloc(state->groups[i].captures); + + goto error; + } + + state->groups[g].captures = captures; + state->groups[g].capacity = 1; + } + } + } + + /* Adjust boundaries. */ + if (start < 0) + start += str_info->length; + if (start < 0) + start = 0; + else if (start > str_info->length) + start = str_info->length; + + if (end < 0) + end += str_info->length; + if (end < 0) + end = 0; + else if (end > str_info->length) + end = str_info->length; + + state->overlapped = overlapped; + state->min_width = pattern->min_width; + + /* Initialise the getters and setters for the character size. */ + state->charsize = str_info->charsize; + state->is_unicode = str_info->is_unicode; + + /* Are we using a buffer object? If so, we need to copy the info. */ + state->should_release = str_info->should_release; + if (state->should_release) + state->view = str_info->view; + + switch (state->charsize) { + case 1: + state->char_at = bytes1_char_at; + state->set_char_at = bytes1_set_char_at; + state->point_to = bytes1_point_to; + break; + case 2: + state->char_at = bytes2_char_at; + state->set_char_at = bytes2_set_char_at; + state->point_to = bytes2_point_to; + break; + case 4: + state->char_at = bytes4_char_at; + state->set_char_at = bytes4_set_char_at; + state->point_to = bytes4_point_to; + break; + default: + goto error; + } + + state->encoding = pattern->encoding; + state->locale_info = pattern->locale_info; + + /* The state object contains a reference to the string and also a pointer + * to its contents. + * + * The documentation says that the end of the slice behaves like the end of + * the string. + */ + state->text = str_info->characters; + state->text_length = str_info->length; + + /* Open start and closed end bounds, like in re module. */ + state->text_start = 0; + state->text_end = end; + + state->slice_start = start; + state->slice_end = end; + + state->reverse = (pattern->flags & RE_FLAG_REVERSE) != 0; + if (partial) + state->partial_side = state->reverse ? RE_PARTIAL_LEFT : + RE_PARTIAL_RIGHT; + else + state->partial_side = RE_PARTIAL_NONE; + + state->text_pos = state->reverse ? state->slice_end : state->slice_start; + + /* Point to the final newline and line separator if it's at the end of the + * string, otherwise just -1. + */ + state->final_newline = -1; + state->final_line_sep = -1; + final_pos = state->text_end - 1; + if (final_pos >= 0) { + Py_UCS4 ch; + + ch = state->char_at(state->text, final_pos); + if (ch == 0x0A) { + /* The string ends with LF. */ + state->final_newline = final_pos; + state->final_line_sep = final_pos; + + /* Does the string end with CR/LF? */ + --final_pos; + if (final_pos >= 0 && state->char_at(state->text, final_pos) == + 0x0D) + state->final_line_sep = final_pos; + } else { + /* The string doesn't end with LF, but it could be another kind of + * line separator. + */ + if (state->encoding->is_line_sep(ch)) + state->final_line_sep = final_pos; + } + } + + /* If the 'new' behaviour is enabled then split correctly on zero-width + * matches. + */ + state->version_0 = (pattern->flags & RE_FLAG_VERSION1) == 0; + state->must_advance = FALSE; + + state->pattern = pattern; + state->string = string; + + if (pattern->repeat_count) { + if (pattern->repeats_storage) { + state->repeats = pattern->repeats_storage; + pattern->repeats_storage = NULL; + } else { + state->repeats = (RE_RepeatData*)re_alloc(pattern->repeat_count * + sizeof(RE_RepeatData)); + if (!state->repeats) + goto error; + memset(state->repeats, 0, pattern->repeat_count * + sizeof(RE_RepeatData)); + } + } + + if (pattern->fuzzy_count) { + state->fuzzy_guards = (RE_FuzzyGuards*)re_alloc(pattern->fuzzy_count * + sizeof(RE_FuzzyGuards)); + if (!state->fuzzy_guards) + goto error; + memset(state->fuzzy_guards, 0, pattern->fuzzy_count * + sizeof(RE_FuzzyGuards)); + } + + state->fuzzy_changes.capacity = 0; + state->fuzzy_changes.count = 0; + state->fuzzy_changes.items = NULL; + + Py_INCREF(state->pattern); + Py_INCREF(state->string); + + /* Multithreading is allowed during matching when explicitly enabled or on + * immutable strings. + */ + switch (concurrent) { + case RE_CONC_NO: + state->is_multithreaded = FALSE; + break; + case RE_CONC_YES: + state->is_multithreaded = TRUE; + break; + default: + state->is_multithreaded = PyUnicode_Check(string) || + PyBytes_Check(string); + break; + } + + state->timeout = timeout; + state->start_time = timeout == RE_NO_TIMEOUT ? 0 : clock(); + + /* A state struct can sometimes be shared across threads. In such + * instances, if multithreading is enabled we need to protect the state + * with a lock (mutex) during matching. + */ + if (state->is_multithreaded && use_lock) + state->lock = PyThread_allocate_lock(); + + for (p = 0; p < MAX_SEARCH_POSITIONS; p++) + state->search_positions[p].start_pos = -1; + + return TRUE; + +error: + re_dealloc(state->group_call_guard_list); + re_dealloc(state->repeats); + dealloc_groups(state->groups, pattern->true_group_count); + re_dealloc(state->fuzzy_guards); + state->repeats = NULL; + state->groups = NULL; + state->fuzzy_guards = NULL; + return FALSE; +} + +/* Checks that the string has the same charsize as the pattern. */ +Py_LOCAL_INLINE(BOOL) check_compatible(PatternObject* pattern, BOOL unicode) { + if (PyBytes_Check(pattern->pattern)) { + if (unicode) { + PyErr_SetString(PyExc_TypeError, + "cannot use a bytes pattern on a string-like object"); + return FALSE; + } + } else { + if (!unicode) { + PyErr_SetString(PyExc_TypeError, + "cannot use a string pattern on a bytes-like object"); + return FALSE; + } + } + + return TRUE; +} + +/* Releases the string's buffer, if necessary. */ +Py_LOCAL_INLINE(void) release_buffer(RE_StringInfo* str_info) { + if (str_info->should_release) + PyBuffer_Release(&str_info->view); +} + +/* Initialises a state object. */ +Py_LOCAL_INLINE(BOOL) state_init(RE_State* state, PatternObject* pattern, + PyObject* string, Py_ssize_t start, Py_ssize_t end, BOOL overlapped, int + concurrent, BOOL partial, BOOL use_lock, BOOL visible_captures, BOOL + match_all, Py_ssize_t timeout) { + RE_StringInfo str_info; + + /* Get the string to search or match. */ + if (!get_string(string, &str_info)) + return FALSE; + + /* If we fail to initialise the state then we need to release the buffer if + * the string is a buffer object. + */ + if (!check_compatible(pattern, str_info.is_unicode)) { + release_buffer(&str_info); + return FALSE; + } + + if (!state_init_2(state, pattern, string, &str_info, start, end, + overlapped, concurrent, partial, use_lock, visible_captures, match_all, + timeout)) { + release_buffer(&str_info); + return FALSE; + } + + /* The state has been initialised successfully, so now the state has the + * responsibility of releasing the buffer if the string is a buffer object. + */ + return TRUE; +} + +/* Deallocates repeat data. */ +Py_LOCAL_INLINE(void) dealloc_repeats(RE_RepeatData* repeats, size_t + repeat_count) { + size_t i; + + if (!repeats) + return; + + for (i = 0; i < repeat_count; i++) { + re_dealloc(repeats[i].body_guard_list.spans); + re_dealloc(repeats[i].tail_guard_list.spans); + } + + re_dealloc(repeats); +} + +/* Deallocates fuzzy guards. */ +Py_LOCAL_INLINE(void) dealloc_fuzzy_guards(RE_FuzzyGuards* guards, size_t + fuzzy_count) { + size_t i; + + if (!guards) + return; + + for (i = 0; i < fuzzy_count; i++) { + re_dealloc(guards[i].body_guard_list.spans); + re_dealloc(guards[i].tail_guard_list.spans); + } + + re_dealloc(guards); +} + +/* Finalises a state object, discarding its contents. */ +Py_LOCAL_INLINE(void) state_fini(RE_State* state) { + PatternObject* pattern; + size_t i; + + /* Discard the lock (mutex) if there's one. */ + if (state->lock) + PyThread_free_lock(state->lock); + + pattern = state->pattern; + + /* If possible cache the storage of bstack. */ + if (!pattern->stack_storage) { + pattern->stack_storage = state->bstack.storage; + pattern->stack_capacity = state->bstack.capacity; + state->bstack.storage = NULL; + state->bstack.capacity = 0; + state->bstack.count = 0; + + /* Limit the size of the cached storage to <= 64KB. */ + if (pattern->stack_capacity > 0x10000) { + BYTE* new_storage; + + new_storage = re_realloc(pattern->stack_storage, 0x10000); + if (new_storage) { + pattern->stack_storage = new_storage; + pattern->stack_capacity = 0x10000; + } + } + } + + /* Clear the stacks. */ + ByteStack_fini(state, &state->sstack); + ByteStack_fini(state, &state->bstack); + ByteStack_fini(state, &state->pstack); + + if (state->best_match_groups) + dealloc_groups(state->best_match_groups, pattern->true_group_count); + + if (pattern->groups_storage) + dealloc_groups(state->groups, pattern->true_group_count); + else + pattern->groups_storage = state->groups; + + if (pattern->repeats_storage) + dealloc_repeats(state->repeats, pattern->repeat_count); + else + pattern->repeats_storage = state->repeats; + + for (i = 0; i < pattern->call_ref_info_count; i++) + re_dealloc(state->group_call_guard_list[i].spans); + + if (state->group_call_guard_list) + re_dealloc(state->group_call_guard_list); + + if (state->fuzzy_guards) + dealloc_fuzzy_guards(state->fuzzy_guards, pattern->fuzzy_count); + + re_dealloc(state->fuzzy_changes.items); + + Py_DECREF(state->pattern); + Py_DECREF(state->string); + + if (state->should_release) + PyBuffer_Release(&state->view); +} + +/* Converts a string index to an integer. + * + * If the index is None then the default will be returned. + */ +Py_LOCAL_INLINE(Py_ssize_t) as_string_index(PyObject* obj, Py_ssize_t def) { + Py_ssize_t value; + + if (obj == Py_None) + return def; + + value = PyLong_AsLong(obj); + if (!(value == -1 && PyErr_Occurred())) + return value; + + set_error(RE_ERROR_INDEX, NULL); + return -1; +} + +/* Deallocates a MatchObject. */ +static void match_dealloc(PyObject* self_) { + MatchObject* self; + + self = (MatchObject*)self_; + + Py_XDECREF(self->string); + Py_XDECREF(self->substring); + Py_DECREF(self->pattern); + if (self->groups) + re_dealloc(self->groups); + if (self->fuzzy_changes) + re_dealloc(self->fuzzy_changes); + Py_XDECREF(self->regs); + PyObject_DEL(self); +} + +/* Ensures that the string is the immutable Unicode string or bytestring. + * DECREFs the original string if a copy is returned. + */ +Py_LOCAL_INLINE(PyObject*) ensure_immutable(PyObject* string) { + PyObject* new_string; + + if (PyUnicode_CheckExact(string) || PyBytes_CheckExact(string)) + return string; + + if (PyUnicode_Check(string)) + new_string = PyUnicode_FromObject(string); + else + new_string = PyBytes_FromObject(string); + + Py_DECREF(string); + + return new_string; +} + +/* Restricts a value to a range. */ +Py_LOCAL_INLINE(Py_ssize_t) limited_range(Py_ssize_t value, Py_ssize_t lower, + Py_ssize_t upper) { + if (value < lower) + return lower; + + if (value > upper) + return upper; + + return value; +} + +/* Gets a slice from a Unicode string. */ +Py_LOCAL_INLINE(PyObject*) unicode_slice(PyObject* string, Py_ssize_t start, + Py_ssize_t end) { + Py_ssize_t length; + + length = PyUnicode_GET_LENGTH(string); + start = limited_range(start, 0, length); + end = limited_range(end, 0, length); + + return PyUnicode_Substring(string, start, end); +} + +/* Gets a slice from a bytestring. */ +Py_LOCAL_INLINE(PyObject*) bytes_slice(PyObject* string, Py_ssize_t start, + Py_ssize_t end) { + Py_ssize_t length; + char* buffer; + + length = PyBytes_GET_SIZE(string); + start = limited_range(start, 0, length); + end = limited_range(end, 0, length); + + buffer = PyBytes_AsString(string); + + return PyBytes_FromStringAndSize(buffer + start, end - start); +} + +/* Gets a slice from a string, returning either a Unicode string or a + * bytestring. + */ +Py_LOCAL_INLINE(PyObject*) get_slice(PyObject* string, Py_ssize_t start, + Py_ssize_t end) { + if (PyUnicode_Check(string)) + return unicode_slice(string, start, end); + + if (PyBytes_Check(string)) + return bytes_slice(string, start, end); + + return ensure_immutable(PySequence_GetSlice(string, start, end)); +} + +/* Gets a MatchObject's group by integer index. */ +static PyObject* match_get_group_by_index(MatchObject* self, Py_ssize_t index, + PyObject* def) { + RE_GroupData* group; + RE_GroupSpan* span; + + if (index < 0 || (size_t)index > self->group_count) { + /* Raise error if we were given a bad group number. */ + set_error(RE_ERROR_NO_SUCH_GROUP, NULL); + return NULL; + } + + if (index == 0) + return get_slice(self->substring, self->match_start - + self->substring_offset, self->match_end - self->substring_offset); + + /* Capture group indexes are 1-based (excluding group 0, which is the + * entire matched string). + */ + group = &self->groups[index - 1]; + + if (group->current < 0) { + /* Return default value if the string or group is undefined. */ + Py_INCREF(def); + return def; + } + + span = &group->captures[group->current]; + + return get_slice(self->substring, span->start - self->substring_offset, + span->end - self->substring_offset); +} + +/* Gets a MatchObject's start by integer index. */ +static PyObject* match_get_start_by_index(MatchObject* self, Py_ssize_t index) + { + RE_GroupData* group; + RE_GroupSpan* span; + + if (index < 0 || (size_t)index > self->group_count) { + /* Raise error if we were given a bad group number. */ + set_error(RE_ERROR_NO_SUCH_GROUP, NULL); + return NULL; + } + + if (index == 0) + return Py_BuildValue("n", self->match_start); + + /* Capture group indexes are 1-based (excluding group 0, which is the + * entire matched string). + */ + group = &self->groups[index - 1]; + + if (group->current < 0) + return Py_BuildValue("n", (Py_ssize_t)-1); + + span = &group->captures[group->current]; + + return Py_BuildValue("n", span->start); +} + +/* Gets a MatchObject's starts by integer index. */ +static PyObject* match_get_starts_by_index(MatchObject* self, Py_ssize_t index) + { + RE_GroupData* group; + PyObject* result; + PyObject* item; + size_t i; + + if (index < 0 || (size_t)index > self->group_count) { + /* Raise error if we were given a bad group number. */ + set_error(RE_ERROR_NO_SUCH_GROUP, NULL); + return NULL; + } + + if (index == 0) { + result = PyList_New(1); + if (!result) + return NULL; + + item = Py_BuildValue("n", self->match_start); + if (!item) + goto error; + + /* PyList_SetItem borrows the reference. */ + PyList_SetItem(result, 0, item); + + return result; + } + + /* Capture group indexes are 1-based (excluding group 0, which is the + * entire matched string). + */ + group = &self->groups[index - 1]; + + result = PyList_New((Py_ssize_t)group->count); + if (!result) + return NULL; + + for (i = 0; i < group->count; i++) { + item = Py_BuildValue("n", group->captures[i].start); + if (!item) + goto error; + + /* PyList_SetItem borrows the reference. */ + PyList_SetItem(result, i, item); + } + + return result; + +error: + Py_DECREF(result); + return NULL; +} + +/* Gets a MatchObject's end by integer index. */ +static PyObject* match_get_end_by_index(MatchObject* self, Py_ssize_t index) { + RE_GroupData* group; + RE_GroupSpan* span; + + if (index < 0 || (size_t)index > self->group_count) { + /* Raise error if we were given a bad group number. */ + set_error(RE_ERROR_NO_SUCH_GROUP, NULL); + return NULL; + } + + if (index == 0) + return Py_BuildValue("n", self->match_end); + + /* Capture group indexes are 1-based (excluding group 0, which is the + * entire matched string). + */ + group = &self->groups[index - 1]; + + if (group->current < 0) + return Py_BuildValue("n", (Py_ssize_t)-1); + + span = &group->captures[group->current]; + + return Py_BuildValue("n", span->end); +} + +/* Gets a MatchObject's ends by integer index. */ +static PyObject* match_get_ends_by_index(MatchObject* self, Py_ssize_t index) { + RE_GroupData* group; + PyObject* result; + PyObject* item; + size_t i; + + if (index < 0 || (size_t)index > self->group_count) { + /* Raise error if we were given a bad group number. */ + set_error(RE_ERROR_NO_SUCH_GROUP, NULL); + return NULL; + } + + if (index == 0) { + result = PyList_New(1); + if (!result) + return NULL; + + item = Py_BuildValue("n", self->match_end); + if (!item) + goto error; + + /* PyList_SetItem borrows the reference. */ + PyList_SetItem(result, 0, item); + + return result; + } + + /* Capture group indexes are 1-based (excluding group 0, which is the + * entire matched string). + */ + group = &self->groups[index - 1]; + + result = PyList_New((Py_ssize_t)group->count); + if (!result) + return NULL; + + for (i = 0; i < group->count; i++) { + item = Py_BuildValue("n", group->captures[i].end); + if (!item) + goto error; + + /* PyList_SetItem borrows the reference. */ + PyList_SetItem(result, i, item); + } + + return result; + +error: + Py_DECREF(result); + return NULL; +} + +/* Gets a MatchObject's span by integer index. */ +static PyObject* match_get_span_by_index(MatchObject* self, Py_ssize_t index) { + RE_GroupData* group; + RE_GroupSpan* span; + + if (index < 0 || (size_t)index > self->group_count) { + /* Raise error if we were given a bad group number. */ + set_error(RE_ERROR_NO_SUCH_GROUP, NULL); + return NULL; + } + + if (index == 0) + return Py_BuildValue("nn", self->match_start, self->match_end); + + /* Capture group indexes are 1-based (excluding group 0, which is the + * entire matched string). + */ + group = &self->groups[index - 1]; + + if (group->current < 0) + return Py_BuildValue("nn", (Py_ssize_t)-1, (Py_ssize_t)-1); + + span = &group->captures[group->current]; + + return Py_BuildValue("nn", span->start, span->end); +} + +/* Gets a MatchObject's spans by integer index. */ +static PyObject* match_get_spans_by_index(MatchObject* self, Py_ssize_t index) + { + PyObject* result; + PyObject* item; + RE_GroupData* group; + size_t i; + + if (index < 0 || (size_t)index > self->group_count) { + /* Raise error if we were given a bad group number. */ + set_error(RE_ERROR_NO_SUCH_GROUP, NULL); + return NULL; + } + + if (index == 0) { + result = PyList_New(1); + if (!result) + return NULL; + + item = Py_BuildValue("nn", self->match_start, self->match_end); + if (!item) + goto error; + + /* PyList_SetItem borrows the reference. */ + PyList_SetItem(result, 0, item); + + return result; + } + + /* Capture group indexes are 1-based (excluding group 0, which is the + * entire matched string). + */ + group = &self->groups[index - 1]; + + result = PyList_New((Py_ssize_t)group->count); + if (!result) + return NULL; + + for (i = 0; i < group->count; i++) { + item = Py_BuildValue("nn", group->captures[i].start, + group->captures[i].end); + if (!item) + goto error; + + /* PyList_SetItem borrows the reference. */ + PyList_SetItem(result, i, item); + } + + return result; + +error: + Py_DECREF(result); + return NULL; +} + +/* Gets a MatchObject's captures by integer index. */ +static PyObject* match_get_captures_by_index(MatchObject* self, Py_ssize_t + index) { + PyObject* result; + PyObject* slice; + RE_GroupData* group; + size_t i; + + if (index < 0 || (size_t)index > self->group_count) { + /* Raise error if we were given a bad group number. */ + set_error(RE_ERROR_NO_SUCH_GROUP, NULL); + return NULL; + } + + if (index == 0) { + result = PyList_New(1); + if (!result) + return NULL; + + slice = get_slice(self->substring, self->match_start - + self->substring_offset, self->match_end - self->substring_offset); + if (!slice) + goto error; + + /* PyList_SetItem borrows the reference. */ + PyList_SetItem(result, 0, slice); + + return result; + } + + /* Capture group indexes are 1-based (excluding group 0, which is the + * entire matched string). + */ + group = &self->groups[index - 1]; + + result = PyList_New((Py_ssize_t)group->count); + if (!result) + return NULL; + + for (i = 0; i < group->count; i++) { + slice = get_slice(self->substring, group->captures[i].start - + self->substring_offset, group->captures[i].end - + self->substring_offset); + if (!slice) + goto error; + + /* PyList_SetItem borrows the reference. */ + PyList_SetItem(result, i, slice); + } + + return result; + +error: + Py_DECREF(result); + return NULL; +} + +/* Converts a group index to an integer. */ +Py_LOCAL_INLINE(Py_ssize_t) as_group_index(PyObject* obj) { + Py_ssize_t value; + + value = PyLong_AsLong(obj); + if (!(value == -1 && PyErr_Occurred())) + return value; + + set_error(RE_ERROR_INDEX, NULL); + return -1; +} + +/* Gets a MatchObject's group index. + * + * The supplied index can be an integer or a string (group name) object. + */ +Py_LOCAL_INLINE(Py_ssize_t) match_get_group_index(MatchObject* self, PyObject* + index, BOOL allow_neg) { + Py_ssize_t group; + + /* Is the index an integer? */ + group = as_group_index(index); + if (!(group == -1 && PyErr_Occurred())) { + Py_ssize_t min_group = 0; + + /* Adjust negative indices where valid and allowed. */ + if (group < 0 && allow_neg) { + group += (Py_ssize_t)self->group_count + 1; + min_group = 1; + } + + if (min_group <= group && (size_t)group <= self->group_count) + return group; + + return -1; + } + + PyErr_Clear(); + + /* The index might be a group name. */ + if (self->pattern->groupindex) { + /* Look up the name. */ + index = PyObject_GetItem(self->pattern->groupindex, index); + if (index) { + /* Check that we have an integer. */ + group = as_group_index(index); + Py_DECREF(index); + if (!(group == -1 && PyErr_Occurred())) + return group; + } + } + + PyErr_Clear(); + return -1; +} + +/* Gets a MatchObject's group by object index. */ +Py_LOCAL_INLINE(PyObject*) match_get_group(MatchObject* self, PyObject* index, + PyObject* def, BOOL allow_neg) { + /* Check that the index is an integer or a string. */ + if (PyLong_Check(index) || PyUnicode_Check(index) || PyBytes_Check(index)) + return match_get_group_by_index(self, match_get_group_index(self, + index, allow_neg), def); + + set_error(RE_ERROR_GROUP_INDEX_TYPE, index); + return NULL; +} + +/* Gets info from a MatchObject by object index. */ +Py_LOCAL_INLINE(PyObject*) get_by_arg(MatchObject* self, PyObject* index, + RE_GetByIndexFunc get_by_index) { + /* Check that the index is an integer or a string. */ + if (PyLong_Check(index) || PyUnicode_Check(index) || PyBytes_Check(index)) + return get_by_index(self, match_get_group_index(self, index, FALSE)); + + set_error(RE_ERROR_GROUP_INDEX_TYPE, index); + return NULL; +} + +/* MatchObject's 'group' method. */ +static PyObject* match_group(MatchObject* self, PyObject* args) { + Py_ssize_t size; + PyObject* result; + Py_ssize_t i; + + size = PyTuple_GET_SIZE(args); + + switch (size) { + case 0: + /* group() */ + result = match_get_group_by_index(self, 0, Py_None); + break; + case 1: + /* group(x). PyTuple_GET_ITEM borrows the reference. */ + result = match_get_group(self, PyTuple_GET_ITEM(args, 0), Py_None, + FALSE); + break; + default: + /* group(x, y, z, ...) */ + /* Fetch multiple items. */ + result = PyTuple_New(size); + if (!result) + return NULL; + + for (i = 0; i < size; i++) { + PyObject* item; + + /* PyTuple_GET_ITEM borrows the reference. */ + item = match_get_group(self, PyTuple_GET_ITEM(args, i), Py_None, + FALSE); + if (!item) { + Py_DECREF(result); + return NULL; + } + + /* PyTuple_SET_ITEM borrows the reference. */ + PyTuple_SET_ITEM(result, i, item); + } + break; + } + + return result; +} + +/* Generic method for getting info from a MatchObject. */ +Py_LOCAL_INLINE(PyObject*) get_from_match(MatchObject* self, PyObject* args, + RE_GetByIndexFunc get_by_index) { + Py_ssize_t size; + PyObject* result; + Py_ssize_t i; + + size = PyTuple_GET_SIZE(args); + + switch (size) { + case 0: + /* get() */ + result = get_by_index(self, 0); + break; + case 1: + /* get(x). PyTuple_GET_ITEM borrows the reference. */ + result = get_by_arg(self, PyTuple_GET_ITEM(args, 0), get_by_index); + break; + default: + /* get(x, y, z, ...) */ + /* Fetch multiple items. */ + result = PyTuple_New(size); + if (!result) + return NULL; + + for (i = 0; i < size; i++) { + PyObject* item; + + /* PyTuple_GET_ITEM borrows the reference. */ + item = get_by_arg(self, PyTuple_GET_ITEM(args, i), get_by_index); + if (!item) { + Py_DECREF(result); + return NULL; + } + + /* PyTuple_SET_ITEM borrows the reference. */ + PyTuple_SET_ITEM(result, i, item); + } + break; + } + + return result; +} + +/* MatchObject's 'start' method. */ +static PyObject* match_start(MatchObject* self, PyObject* args) { + return get_from_match(self, args, match_get_start_by_index); +} + +/* MatchObject's 'starts' method. */ +static PyObject* match_starts(MatchObject* self, PyObject* args) { + return get_from_match(self, args, match_get_starts_by_index); +} + +/* MatchObject's 'end' method. */ +static PyObject* match_end(MatchObject* self, PyObject* args) { + return get_from_match(self, args, match_get_end_by_index); +} + +/* MatchObject's 'ends' method. */ +static PyObject* match_ends(MatchObject* self, PyObject* args) { + return get_from_match(self, args, match_get_ends_by_index); +} + +/* MatchObject's 'span' method. */ +static PyObject* match_span(MatchObject* self, PyObject* args) { + return get_from_match(self, args, match_get_span_by_index); +} + +/* MatchObject's 'spans' method. */ +static PyObject* match_spans(MatchObject* self, PyObject* args) { + return get_from_match(self, args, match_get_spans_by_index); +} + +/* MatchObject's 'allspans' method. */ +static PyObject* match_allspans(MatchObject* self) { + PyObject* list; + size_t i; + PyObject* result; + + list = PyList_New(0); + if (!list) + return NULL; + + /* Include all the groups, including group 0 (the whole match). */ + for (i = 0; i <= self->group_count; i++) { + PyObject* span; + int status; + + span = match_get_spans_by_index(self, i); + if (!span) + goto error; + + status = PyList_Append(list, span); + Py_DECREF(span); + if (status < 0) + goto error; + } + + result = PyList_AsTuple(list); + Py_DECREF(list); + return result; + +error: + Py_DECREF(list); + return NULL; +} + +/* MatchObject's 'captures' method. */ +static PyObject* match_captures(MatchObject* self, PyObject* args) { + return get_from_match(self, args, match_get_captures_by_index); +} + +/* MatchObject's 'allcaptures' method. */ +static PyObject* match_allcaptures(MatchObject* self) { + PyObject* list; + size_t i; + PyObject* result; + + list = PyList_New(0); + if (!list) + return NULL; + + /* Include all the groups, including group 0 (the whole match). */ + for (i = 0; i <= self->group_count; i++) { + PyObject* span; + int status; + + span = match_get_captures_by_index(self, i); + if (!span) + goto error; + + status = PyList_Append(list, span); + Py_DECREF(span); + if (status < 0) + goto error; + } + + result = PyList_AsTuple(list); + Py_DECREF(list); + return result; + +error: + Py_DECREF(list); + return NULL; +} + +/* MatchObject's 'groups' method. */ +static PyObject* match_groups(MatchObject* self, PyObject* args, PyObject* + kwargs) { + PyObject* result; + size_t g; + + PyObject* def = Py_None; + static char* kwlist[] = { "default", NULL }; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:groups", kwlist, &def)) + return NULL; + + result = PyTuple_New((Py_ssize_t)self->group_count); + if (!result) + return NULL; + + /* Group 0 is the entire matched portion of the string. */ + for (g = 0; g < self->group_count; g++) { + PyObject* item; + + item = match_get_group_by_index(self, (Py_ssize_t)g + 1, def); + if (!item) + goto error; + + /* PyTuple_SET_ITEM borrows the reference. */ + PyTuple_SET_ITEM(result, g, item); + } + + return result; + +error: + Py_DECREF(result); + return NULL; +} + +/* MatchObject's 'groupdict' method. */ +static PyObject* match_groupdict(MatchObject* self, PyObject* args, PyObject* + kwargs) { + PyObject* result; + PyObject* keys; + Py_ssize_t g; + + PyObject* def = Py_None; + static char* kwlist[] = { "default", NULL }; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:groupdict", kwlist, + &def)) + return NULL; + + result = PyDict_New(); + if (!result || !self->pattern->groupindex) + return result; + + keys = PyMapping_Keys(self->pattern->groupindex); + if (!keys) + goto failed; + + for (g = 0; g < PyList_Size(keys); g++) { + PyObject* key; + PyObject* value; + int status; + + /* PyList_GetItem borrows a reference. */ + key = PyList_GetItem(keys, g); + if (!key) + goto failed; + + value = match_get_group(self, key, def, FALSE); + if (!value) + goto failed; + + status = PyDict_SetItem(result, key, value); + Py_DECREF(value); + if (status < 0) + goto failed; + } + + Py_DECREF(keys); + + return result; + +failed: + Py_XDECREF(keys); + Py_DECREF(result); + return NULL; +} + +/* MatchObject's 'capturesdict' method. */ +static PyObject* match_capturesdict(MatchObject* self) { + PyObject* result; + PyObject* keys; + Py_ssize_t g; + + result = PyDict_New(); + if (!result || !self->pattern->groupindex) + return result; + + keys = PyMapping_Keys(self->pattern->groupindex); + if (!keys) + goto failed; + + for (g = 0; g < PyList_Size(keys); g++) { + PyObject* key; + Py_ssize_t group; + PyObject* captures; + int status; + + /* PyList_GetItem borrows a reference. */ + key = PyList_GetItem(keys, g); + if (!key) + goto failed; + + group = match_get_group_index(self, key, FALSE); + if (group < 0) + goto failed; + + captures = match_get_captures_by_index(self, group); + if (!captures) + goto failed; + + status = PyDict_SetItem(result, key, captures); + Py_DECREF(captures); + if (status < 0) + goto failed; + } + + Py_DECREF(keys); + + return result; + +failed: + Py_XDECREF(keys); + Py_DECREF(result); + return NULL; +} + +/* Gets a Python object by name from a named module. */ +Py_LOCAL_INLINE(PyObject*) get_object(char* module_name, char* object_name) { + PyObject* module; + PyObject* object; + + module = PyImport_ImportModule(module_name); + if (!module) + return NULL; + + object = PyObject_GetAttrString(module, object_name); + Py_DECREF(module); + + return object; +} + +/* Calls a function in a module. */ +Py_LOCAL_INLINE(PyObject*) call(char* module_name, char* function_name, + PyObject* args) { + PyObject* function; + PyObject* result; + + if (!args) + return NULL; + + function = get_object(module_name, function_name); + if (!function) + return NULL; + + result = PyObject_CallObject(function, args); + Py_DECREF(function); + Py_DECREF(args); + + return result; +} + +/* Gets a replacement item from the replacement list. + * + * The replacement item could be a string literal or a group. + */ +Py_LOCAL_INLINE(PyObject*) get_match_replacement(MatchObject* self, PyObject* + item, size_t group_count) { + Py_ssize_t index; + + if (PyUnicode_Check(item) || PyBytes_Check(item)) { + /* It's a literal, which can be added directly to the list. */ + + /* ensure_immutable will DECREF the original item if it has to make an + * immutable copy, but that original item might have a borrowed + * reference, so we must INCREF it first in order to ensure it won't be + * destroyed. + */ + Py_INCREF(item); + item = ensure_immutable(item); + return item; + } + + /* Is it a group reference? */ + index = as_group_index(item); + if (index == -1 && PyErr_Occurred()) { + /* Not a group either! */ + set_error(RE_ERROR_REPLACEMENT, NULL); + return NULL; + } + + if (index == 0) { + /* The entire matched portion of the string. */ + return get_slice(self->substring, self->match_start - + self->substring_offset, self->match_end - self->substring_offset); + } else if (index >= 1 && (size_t)index <= group_count) { + /* A group. If it didn't match then return None instead. */ + RE_GroupData* group; + + group = &self->groups[index - 1]; + + if (group->current >= 0) { + RE_GroupSpan* span; + + span = &group->captures[group->current]; + + return get_slice(self->substring, span->start - + self->substring_offset, span->end - self->substring_offset); + } else + Py_RETURN_NONE; + } else { + /* No such group. */ + set_error(RE_ERROR_NO_SUCH_GROUP, NULL); + return NULL; + } +} + +/* Initialises the join list. */ +Py_LOCAL_INLINE(void) init_join_list(RE_JoinInfo* join_info, BOOL reversed, + BOOL is_unicode) { + join_info->list = NULL; + join_info->item = NULL; + join_info->reversed = reversed; + join_info->is_unicode = is_unicode; +} + +/* Adds an item to the join list. */ +Py_LOCAL_INLINE(int) add_to_join_list(RE_JoinInfo* join_info, PyObject* item) { + PyObject* new_item; + int status; + + if (join_info->is_unicode) { + if (PyUnicode_CheckExact(item)) { + new_item = item; + Py_INCREF(new_item); + } else { + new_item = PyUnicode_FromObject(item); + if (!new_item) { + set_error(RE_ERROR_NOT_UNICODE, item); + return RE_ERROR_NOT_UNICODE; + } + } + } else { + if (PyBytes_CheckExact(item)) { + new_item = item; + Py_INCREF(new_item); + } else { + new_item = PyBytes_FromObject(item); + if (!new_item) { + set_error(RE_ERROR_NOT_BYTES, item); + return RE_ERROR_NOT_BYTES; + } + } + } + + /* If the list already exists then just add the item to it. */ + if (join_info->list) { + status = PyList_Append(join_info->list, new_item); + if (status < 0) + goto error; + + Py_DECREF(new_item); + return status; + } + + /* If we already have an item then we now have 2(!) and we need to put them + * into a list. + */ + if (join_info->item) { + join_info->list = PyList_New(2); + if (!join_info->list) { + status = RE_ERROR_MEMORY; + goto error; + } + + /* PyList_SetItem borrows the reference. */ + PyList_SetItem(join_info->list, 0, join_info->item); + join_info->item = NULL; + + /* PyList_SetItem borrows the reference. */ + PyList_SetItem(join_info->list, 1, new_item); + return 0; + } + + /* This is the first item. */ + join_info->item = new_item; + + return 0; + +error: + Py_DECREF(new_item); + set_error(status, NULL); + return status; +} + +/* Clears the join list. */ +Py_LOCAL_INLINE(void) clear_join_list(RE_JoinInfo* join_info) { + Py_XDECREF(join_info->list); + Py_XDECREF(join_info->item); +} + +/* Joins a list of bytestrings. */ +Py_LOCAL_INLINE(PyObject*) join_bytestrings(PyObject* list) { + Py_ssize_t count; + Py_ssize_t length; + Py_ssize_t i; + PyObject *result; + char* to_bytes; + + count = PyList_Size(list); + + /* How long will the result be? */ + length = 0; + + for (i = 0; i < count; i++) + length += PyBytes_Size(PyList_GetItem(list, i)); + + /* Create the resulting bytestring, but uninitialised. */ + result = PyBytes_FromStringAndSize(NULL, length); + if (!result) + return NULL; + + /* Fill the resulting bytestring. */ + to_bytes = PyBytes_AsString(result); + length = 0; + + for (i = 0; i < count; i++) { + PyObject* bytestring; + char* from_bytes; + Py_ssize_t from_length; + + bytestring = PyList_GetItem(list, i); + from_bytes = PyBytes_AsString(bytestring); + from_length = PyBytes_Size(bytestring); + memmove(to_bytes + length, from_bytes, from_length); + length += from_length; + } + + return result; +} + +/* Joins a list of strings. */ +Py_LOCAL_INLINE(PyObject*) join_strings(PyObject* list) { + PyObject* joiner; + PyObject* result; + + joiner = PyUnicode_FromString(""); + if (!joiner) + return NULL; + + result = PyUnicode_Join(joiner, list); + Py_DECREF(joiner); + + return result; +} + +/* Joins together a list of strings for pattern_subx. */ +Py_LOCAL_INLINE(PyObject*) join_list_info(RE_JoinInfo* join_info) { + /* If the list already exists then just do the join. */ + if (join_info->list) { + PyObject* result; + + if (join_info->reversed) + /* The list needs to be reversed before being joined. */ + PyList_Reverse(join_info->list); + + if (join_info->is_unicode) + /* Concatenate the Unicode strings. */ + result = join_strings(join_info->list); + else + /* Concatenate the bytestrings. */ + result = join_bytestrings(join_info->list); + + clear_join_list(join_info); + + return result; + } + + /* If we have only 1 item, so we'll just return it. */ + if (join_info->item) + return join_info->item; + + /* There are no items, so return an empty string. */ + if (join_info->is_unicode) + return PyUnicode_New(0, 0); + else + return PyBytes_FromString(""); +} + +/* Checks whether a string replacement is a literal. + * + * To keep it simple we'll say that a literal is a string which can be used + * as-is. + * + * Returns its length if it is a literal, otherwise -1. + */ +Py_LOCAL_INLINE(Py_ssize_t) check_replacement_string(PyObject* str_replacement, + unsigned char special_char) { + RE_StringInfo str_info; + Py_UCS4 (*char_at)(void* text, Py_ssize_t pos); + Py_ssize_t pos; + + if (!get_string(str_replacement, &str_info)) + return -1; + + switch (str_info.charsize) { + case 1: + char_at = bytes1_char_at; + break; + case 2: + char_at = bytes2_char_at; + break; + case 4: + char_at = bytes4_char_at; + break; + default: + release_buffer(&str_info); + return -1; + } + + for (pos = 0; pos < str_info.length; pos++) { + if (char_at(str_info.characters, pos) == special_char) { + release_buffer(&str_info); + return -1; + } + } + + release_buffer(&str_info); + + return str_info.length; +} + +/* MatchObject's 'expand' method. */ +static PyObject* match_expand(MatchObject* self, PyObject* str_template) { + Py_ssize_t literal_length; + PyObject* replacement; + RE_JoinInfo join_info; + Py_ssize_t size; + Py_ssize_t i; + + /* Is the template just a literal? */ + literal_length = check_replacement_string(str_template, '\\'); + if (literal_length >= 0) { + /* It's a literal. */ + Py_INCREF(str_template); + return str_template; + } + + /* Hand the template to the template compiler. */ + replacement = call("regex.regex", "_compile_replacement_helper", + PyTuple_Pack(2, self->pattern, str_template)); + if (!replacement) + return NULL; + + init_join_list(&join_info, FALSE, PyUnicode_Check(self->string)); + + /* Add each part of the template to the list. */ + size = PyList_Size(replacement); + for (i = 0; i < size; i++) { + PyObject* item; + PyObject* str_item; + + /* PyList_GetItem borrows a reference. */ + item = PyList_GetItem(replacement, i); + str_item = get_match_replacement(self, item, self->group_count); + if (!str_item) + goto error; + + /* Add to the list. */ + if (str_item == Py_None) + Py_DECREF(str_item); + else { + int status; + + status = add_to_join_list(&join_info, str_item); + Py_DECREF(str_item); + if (status < 0) + goto error; + } + } + + Py_DECREF(replacement); + + /* Convert the list to a single string (also cleans up join_info). */ + return join_list_info(&join_info); + +error: + clear_join_list(&join_info); + Py_DECREF(replacement); + return NULL; +} + +static PyTypeObject Capture_Type = { + PyVarObject_HEAD_INIT(NULL,0) + "_regex.Capture", + sizeof(MatchObject) +}; + +/* Creates a new CaptureObject. */ +Py_LOCAL_INLINE(PyObject*) make_capture_object(MatchObject** match_indirect, + Py_ssize_t index) { + CaptureObject* capture; + + capture = PyObject_NEW(CaptureObject, &Capture_Type); + if (!capture) + return NULL; + + capture->group_index = index; + capture->match_indirect = match_indirect; + + return (PyObject*)capture; +} + +/* Makes a MatchObject's capture dictionary. */ +Py_LOCAL_INLINE(PyObject*) make_capture_dict(MatchObject* match, MatchObject** + match_indirect) { + PyObject* result; + PyObject* keys; + PyObject* values = NULL; + Py_ssize_t g; + + result = PyDict_New(); + if (!result) + return result; + + keys = PyMapping_Keys(match->pattern->groupindex); + if (!keys) + goto failed; + + values = PyMapping_Values(match->pattern->groupindex); + if (!values) + goto failed; + + for (g = 0; g < PyList_Size(keys); g++) { + PyObject* key; + PyObject* value; + Py_ssize_t v; + int status; + + /* PyList_GetItem borrows a reference. */ + key = PyList_GetItem(keys, g); + if (!key) + goto failed; + + /* PyList_GetItem borrows a reference. */ + value = PyList_GetItem(values, g); + if (!value) + goto failed; + + v = PyLong_AsLong(value); + if (v == -1 && PyErr_Occurred()) + goto failed; + + value = make_capture_object(match_indirect, v); + if (!value) + goto failed; + + status = PyDict_SetItem(result, key, value); + Py_DECREF(value); + if (status < 0) + goto failed; + } + + Py_DECREF(values); + Py_DECREF(keys); + + return result; + +failed: + Py_XDECREF(values); + Py_XDECREF(keys); + Py_DECREF(result); + return NULL; +} + +/* MatchObject's 'expandf' method. */ +static PyObject* match_expandf(MatchObject* self, PyObject* str_template) { + PyObject* format_func; + PyObject* args = NULL; + size_t g; + PyObject* kwargs = NULL; + PyObject* result; + + format_func = PyObject_GetAttrString(str_template, "format"); + if (!format_func) + return NULL; + + args = PyTuple_New((Py_ssize_t)self->group_count + 1); + if (!args) + goto error; + + for (g = 0; g < self->group_count + 1; g++) + /* PyTuple_SetItem borrows the reference. */ + PyTuple_SetItem(args, (Py_ssize_t)g, make_capture_object(&self, + (Py_ssize_t)g)); + + kwargs = make_capture_dict(self, &self); + if (!kwargs) + goto error; + + result = PyObject_Call(format_func, args, kwargs); + + Py_DECREF(kwargs); + Py_DECREF(args); + Py_DECREF(format_func); + + return result; + +error: + Py_XDECREF(args); + Py_DECREF(format_func); + return NULL; +} + +Py_LOCAL_INLINE(PyObject*) make_match_copy(MatchObject* self); + +/* MatchObject's '__copy__' method. */ +static PyObject* match_copy(MatchObject* self, PyObject* unused) { + return make_match_copy(self); +} + +/* MatchObject's '__deepcopy__' method. */ +static PyObject* match_deepcopy(MatchObject* self, PyObject* memo) { + return make_match_copy(self); +} + +/* MatchObject's 'regs' attribute. */ +static PyObject* match_regs(MatchObject* self, void* unused) { + PyObject* regs; + PyObject* item; + size_t g; + + if (self->regs) { + Py_INCREF(self->regs); + + return self->regs; + } + + regs = PyTuple_New((Py_ssize_t)self->group_count + 1); + if (!regs) + return NULL; + + item = Py_BuildValue("nn", self->match_start, self->match_end); + if (!item) + goto error; + + /* PyTuple_SET_ITEM borrows the reference. */ + PyTuple_SET_ITEM(regs, 0, item); + + for (g = 0; g < self->group_count; g++) { + RE_GroupData* group; + + group = &self->groups[g]; + + if (group->current < 0) + item = Py_BuildValue("nn", (Py_ssize_t)-1, (Py_ssize_t)-1); + else { + RE_GroupSpan* span; + + span = &group->captures[group->current]; + item = Py_BuildValue("nn", span->start, span->end); + } + if (!item) + goto error; + + /* PyTuple_SET_ITEM borrows the reference. */ + PyTuple_SET_ITEM(regs, g + 1, item); + } + + self->regs = regs; + + Py_INCREF(self->regs); + + return self->regs; + +error: + Py_DECREF(regs); + return NULL; +} + +/* MatchObject's slice method. */ +Py_LOCAL_INLINE(PyObject*) match_get_group_slice(MatchObject* self, PyObject* + slice) { + Py_ssize_t start; + Py_ssize_t end; + Py_ssize_t step; + Py_ssize_t slice_length; + + if (PySlice_GetIndicesEx(slice, (Py_ssize_t)self->group_count + 1, &start, + &end, &step, &slice_length) < 0) + return NULL; + + if (slice_length <= 0) + return PyTuple_New(0); + else { + PyObject* result; + Py_ssize_t cur; + Py_ssize_t i; + + result = PyTuple_New(slice_length); + if (!result) + return NULL; + + cur = start; + for (i = 0; i < slice_length; i++) { + /* PyTuple_SetItem borrows the reference. */ + PyTuple_SetItem(result, i, match_get_group_by_index(self, cur, + Py_None)); + cur += step; + } + + return result; + } +} + +/* MatchObject's length method. */ +Py_LOCAL_INLINE(Py_ssize_t) match_length(MatchObject* self) { + return (Py_ssize_t)self->group_count + 1; +} + +/* MatchObject's '__getitem__' method. */ +static PyObject* match_getitem(MatchObject* self, PyObject* item) { + if (PySlice_Check(item)) + return match_get_group_slice(self, item); + + return match_get_group(self, item, Py_None, TRUE); +} + +/* Determines the portion of the target string which is covered by the group + * captures. + */ +Py_LOCAL_INLINE(void) determine_target_substring(MatchObject* match, + Py_ssize_t* slice_start, Py_ssize_t* slice_end) { + Py_ssize_t start; + Py_ssize_t end; + size_t g; + + start = match->pos; + end = match->endpos; + + for (g = 0; g < match->group_count; g++) { + RE_GroupData* group; + size_t c; + + group = &match->groups[g]; + + for (c = 0; c < match->groups[g].count; c++) { + RE_GroupSpan* span; + + span = &group->captures[c]; + if (span->start < start) + start = span->start; + if (span->end > end) + end = span->end; + } + } + + *slice_start = start; + *slice_end = end; +} + +/* MatchObject's 'detach_string' method. */ +static PyObject* match_detach_string(MatchObject* self, PyObject* unused) { + if (self->string) { + Py_ssize_t start; + Py_ssize_t end; + PyObject* substring; + + determine_target_substring(self, &start, &end); + + substring = get_slice(self->string, start, end); + if (substring) { + Py_XDECREF(self->substring); + self->substring = substring; + self->substring_offset = start; + + Py_DECREF(self->string); + self->string = NULL; + } + } + + Py_RETURN_NONE; +} + +/* The documentation of a MatchObject. */ +PyDoc_STRVAR(match_group_doc, + "group([group1, ...]) --> string or tuple of strings.\n\ + Return one or more subgroups of the match. If there is a single argument,\n\ + the result is a single string, or None if the group did not contribute to\n\ + the match; if there are multiple arguments, the result is a tuple with one\n\ + item per argument; if there are no arguments, the whole match is returned.\n\ + Group 0 is the whole match."); + +PyDoc_STRVAR(match_start_doc, + "start([group1, ...]) --> int or tuple of ints.\n\ + Return the index of the start of one or more subgroups of the match. If\n\ + there is a single argument, the result is an index, or -1 if the group did\n\ + not contribute to the match; if there are multiple arguments, the result is\n\ + a tuple with one item per argument; if there are no arguments, the index of\n\ + the start of the whole match is returned. Group 0 is the whole match."); + +PyDoc_STRVAR(match_end_doc, + "end([group1, ...]) --> int or tuple of ints.\n\ + Return the index of the end of one or more subgroups of the match. If there\n\ + is a single argument, the result is an index, or -1 if the group did not\n\ + contribute to the match; if there are multiple arguments, the result is a\n\ + tuple with one item per argument; if there are no arguments, the index of\n\ + the end of the whole match is returned. Group 0 is the whole match."); + +PyDoc_STRVAR(match_span_doc, + "span([group1, ...]) --> 2-tuple of int or tuple of 2-tuple of ints.\n\ + Return the span (a 2-tuple of the indices of the start and end) of one or\n\ + more subgroups of the match. If there is a single argument, the result is a\n\ + span, or (-1, -1) if the group did not contribute to the match; if there are\n\ + multiple arguments, the result is a tuple with one item per argument; if\n\ + there are no arguments, the span of the whole match is returned. Group 0 is\n\ + the whole match."); + +PyDoc_STRVAR(match_groups_doc, + "groups(default=None) --> tuple of strings.\n\ + Return a tuple containing all the subgroups of the match. The argument is\n\ + the default for groups that did not participate in the match."); + +PyDoc_STRVAR(match_groupdict_doc, + "groupdict(default=None) --> dict.\n\ + Return a dictionary containing all the named subgroups of the match, keyed\n\ + by the subgroup name. The argument is the value to be given for groups that\n\ + did not participate in the match."); + +PyDoc_STRVAR(match_capturesdict_doc, + "capturesdict() --> dict.\n\ + Return a dictionary containing the captures of all the named subgroups of the\n\ + match, keyed by the subgroup name."); + +PyDoc_STRVAR(match_expand_doc, + "expand(template) --> string.\n\ + Return the string obtained by doing backslash substitution on the template,\n\ + as done by the sub() method."); + +PyDoc_STRVAR(match_expandf_doc, + "expandf(format) --> string.\n\ + Return the string obtained by using the format, as done by the subf()\n\ + method."); + +PyDoc_STRVAR(match_captures_doc, + "captures([group1, ...]) --> list of strings or tuple of list of strings.\n\ + Return the captures of one or more subgroups of the match. If there is a\n\ + single argument, the result is a list of strings; if there are multiple\n\ + arguments, the result is a tuple of lists with one item per argument; if\n\ + there are no arguments, the captures of the whole match is returned. Group\n\ + 0 is the whole match."); + +PyDoc_STRVAR(match_allcaptures_doc, + "allcaptures() --> list of strings or tuple of list of strings.\n\ + Return the captures of all the groups of the match and the whole match."); + +PyDoc_STRVAR(match_starts_doc, + "starts([group1, ...]) --> list of ints or tuple of list of ints.\n\ + Return the indices of the starts of the captures of one or more subgroups of\n\ + the match. If there is a single argument, the result is a list of indices;\n\ + if there are multiple arguments, the result is a tuple of lists with one\n\ + item per argument; if there are no arguments, the indices of the starts of\n\ + the captures of the whole match is returned. Group 0 is the whole match."); + +PyDoc_STRVAR(match_ends_doc, + "ends([group1, ...]) --> list of ints or tuple of list of ints.\n\ + Return the indices of the ends of the captures of one or more subgroups of\n\ + the match. If there is a single argument, the result is a list of indices;\n\ + if there are multiple arguments, the result is a tuple of lists with one\n\ + item per argument; if there are no arguments, the indices of the ends of the\n\ + captures of the whole match is returned. Group 0 is the whole match."); + +PyDoc_STRVAR(match_spans_doc, + "spans([group1, ...]) --> list of 2-tuple of ints or tuple of list of 2-tuple of ints.\n\ + Return the spans (a 2-tuple of the indices of the start and end) of the\n\ + captures of one or more subgroups of the match. If there is a single\n\ + argument, the result is a list of spans; if there are multiple arguments,\n\ + the result is a tuple of lists with one item per argument; if there are no\n\ + arguments, the spans of the captures of the whole match is returned. Group\n\ + 0 is the whole match."); + +PyDoc_STRVAR(match_allspans_doc, + "allspans() --> list of 2-tuple of ints or tuple of list of 2-tuple of ints.\n\ + Return the spans (a 2-tuple of the indices of the start and end) of all the\n\ + captures of all the groups of the match and the whole match."); + +PyDoc_STRVAR(match_detach_string_doc, + "detach_string()\n\ + Detaches the target string from the match object. The 'string' attribute\n\ + will become None."); + +/* MatchObject's methods. */ +static PyMethodDef match_methods[] = { + {"group", (PyCFunction)match_group, METH_VARARGS, match_group_doc}, + {"start", (PyCFunction)match_start, METH_VARARGS, match_start_doc}, + {"end", (PyCFunction)match_end, METH_VARARGS, match_end_doc}, + {"span", (PyCFunction)match_span, METH_VARARGS, match_span_doc}, + {"groups", (PyCFunction)match_groups, METH_VARARGS|METH_KEYWORDS, + match_groups_doc}, + {"groupdict", (PyCFunction)match_groupdict, METH_VARARGS|METH_KEYWORDS, + match_groupdict_doc}, + {"capturesdict", (PyCFunction)match_capturesdict, METH_NOARGS, + match_capturesdict_doc}, + {"expand", (PyCFunction)match_expand, METH_O, match_expand_doc}, + {"expandf", (PyCFunction)match_expandf, METH_O, match_expandf_doc}, + {"captures", (PyCFunction)match_captures, METH_VARARGS, + match_captures_doc}, + {"allcaptures", (PyCFunction)match_allcaptures, METH_NOARGS, + match_allcaptures_doc}, + {"starts", (PyCFunction)match_starts, METH_VARARGS, match_starts_doc}, + {"ends", (PyCFunction)match_ends, METH_VARARGS, match_ends_doc}, + {"spans", (PyCFunction)match_spans, METH_VARARGS, match_spans_doc}, + {"allspans", (PyCFunction)match_allspans, METH_NOARGS, match_allspans_doc}, + {"detach_string", (PyCFunction)match_detach_string, METH_NOARGS, + match_detach_string_doc}, + {"__copy__", (PyCFunction)match_copy, METH_NOARGS}, + {"__deepcopy__", (PyCFunction)match_deepcopy, METH_O}, + {"__getitem__", (PyCFunction)match_getitem, METH_O|METH_COEXIST}, +#if PY_VERSION_HEX >= 0x03090000 + {"__class_getitem__", (PyCFunction)Py_GenericAlias, METH_O|METH_CLASS, + PyDoc_STR("See PEP 585")}, +#endif + {NULL, NULL} +}; + +PyDoc_STRVAR(match_doc, "Match object"); + +/* MatchObject's 'lastindex' attribute. */ +static PyObject* match_lastindex(PyObject* self_, void* unused) { + MatchObject* self; + + self = (MatchObject*)self_; + + if (self->lastindex >= 0) + return Py_BuildValue("n", self->lastindex); + + Py_RETURN_NONE; +} + +/* MatchObject's 'lastgroup' attribute. */ +static PyObject* match_lastgroup(PyObject* self_, void* unused) { + MatchObject* self; + + self = (MatchObject*)self_; + + if (self->pattern->indexgroup && self->lastgroup >= 0) { + PyObject* index; + PyObject* result; + + index = Py_BuildValue("n", self->lastgroup); + if (!index) + return NULL; + + /* PyDict_GetItem returns borrows a reference. */ + result = PyDict_GetItem(self->pattern->indexgroup, index); + Py_DECREF(index); + if (result) { + Py_INCREF(result); + return result; + } + PyErr_Clear(); + } + + Py_RETURN_NONE; +} + +/* MatchObject's 'string' attribute. */ +static PyObject* match_string(PyObject* self_, void* unused) { + MatchObject* self; + + self = (MatchObject*)self_; + + if (self->string) { + Py_INCREF(self->string); + return self->string; + } else + Py_RETURN_NONE; +} + +/* MatchObject's 'fuzzy_counts' attribute. */ +static PyObject* match_fuzzy_counts(PyObject* self_, void* unused) { + MatchObject* self; + + self = (MatchObject*)self_; + + return Py_BuildValue("nnn", self->fuzzy_counts[RE_FUZZY_SUB], + self->fuzzy_counts[RE_FUZZY_INS], self->fuzzy_counts[RE_FUZZY_DEL]); +} + +/* MatchObject's 'fuzzy_changes' attribute. */ +static PyObject* match_fuzzy_changes(PyObject* self_, void* unused) { + MatchObject* self; + PyObject* sub_changes; + PyObject* ins_changes; + PyObject* del_changes; + size_t count; + Py_ssize_t offset; + size_t i; + PyObject* result; + + self = (MatchObject*)self_; + + sub_changes = PyList_New(0); + ins_changes = PyList_New(0); + del_changes = PyList_New(0); + if (!sub_changes || !ins_changes || !del_changes) + goto error; + + count = self->fuzzy_counts[RE_FUZZY_SUB] + self->fuzzy_counts[RE_FUZZY_INS] + + self->fuzzy_counts[RE_FUZZY_DEL]; + offset = 0; + + for (i = 0; i < count; i++) { + RE_FuzzyChange* change; + Py_ssize_t pos; + PyObject* position; + int status; + + change = &self->fuzzy_changes[i]; + + pos = change->pos; + if (change->type == RE_FUZZY_DEL) { + pos += offset; + ++offset; + } + + position = Py_BuildValue("n", pos); + if (!position) + goto error; + + switch (change->type) { + case RE_FUZZY_DEL: + status = PyList_Append(del_changes, position); + break; + case RE_FUZZY_INS: + status = PyList_Append(ins_changes, position); + break; + case RE_FUZZY_SUB: + status = PyList_Append(sub_changes, position); + break; + default: + status = 0; + break; + } + + Py_DECREF(position); + + if (status == -1) + goto error; + } + + result = PyTuple_Pack(3, sub_changes, ins_changes, del_changes); + + Py_DECREF(sub_changes); + Py_DECREF(ins_changes); + Py_DECREF(del_changes); + + return result; + +error: + Py_XDECREF(sub_changes); + Py_XDECREF(ins_changes); + Py_XDECREF(del_changes); + return NULL; +} + +static PyGetSetDef match_getset[] = { + {"lastindex", (getter)match_lastindex, (setter)NULL, + "The group number of the last matched capturing group, or None."}, + {"lastgroup", (getter)match_lastgroup, (setter)NULL, + "The name of the last matched capturing group, or None."}, + {"regs", (getter)match_regs, (setter)NULL, + "A tuple of the spans of the capturing groups."}, + {"string", (getter)match_string, (setter)NULL, + "The string that was searched, or None if it has been detached."}, + {"fuzzy_counts", (getter)match_fuzzy_counts, (setter)NULL, + "A tuple of the number of substitutions, insertions and deletions."}, + {"fuzzy_changes", (getter)match_fuzzy_changes, (setter)NULL, + "A tuple of the positions of the substitutions, insertions and deletions."}, + {NULL} /* Sentinel */ +}; + +static PyMemberDef match_members[] = { + {"re", T_OBJECT, offsetof(MatchObject, pattern), READONLY, + "The regex object that produced this match object."}, + {"pos", T_PYSSIZET, offsetof(MatchObject, pos), READONLY, + "The position at which the regex engine starting searching."}, + {"endpos", T_PYSSIZET, offsetof(MatchObject, endpos), READONLY, + "The final position beyond which the regex engine won't search."}, + {"partial", T_BOOL, offsetof(MatchObject, partial), READONLY, + "Whether it's a partial match."}, + {NULL} /* Sentinel */ +}; + +static PyMappingMethods match_as_mapping = { + (lenfunc)match_length, /* mp_length */ + (binaryfunc)match_getitem, /* mp_subscript */ + 0, /* mp_ass_subscript */ +}; + +static PyTypeObject Match_Type = { + PyVarObject_HEAD_INIT(NULL,0) + "_regex.Match", + sizeof(MatchObject) +}; + +/* Copies the groups. */ +Py_LOCAL_INLINE(RE_GroupData*) copy_groups(RE_GroupData* groups, size_t + group_count) { + size_t span_count; + size_t g; + RE_GroupData* groups_copy; + RE_GroupSpan* spans_copy; + size_t offset; + + /* Calculate the total size of the group info. */ + span_count = 0; + for (g = 0; g < group_count; g++) + span_count += groups[g].count; + + /* Allocate the storage for the group info in a single block. */ + groups_copy = (RE_GroupData*)re_alloc(group_count * sizeof(RE_GroupData) + + span_count * sizeof(RE_GroupSpan)); + if (!groups_copy) + return NULL; + + /* The storage for the spans comes after the other group info. */ + spans_copy = (RE_GroupSpan*)&groups_copy[group_count]; + + /* There's no need to initialise the spans info. */ + memset(groups_copy, 0, group_count * sizeof(RE_GroupData)); + + offset = 0; + for (g = 0; g < group_count; g++) { + RE_GroupData* orig; + RE_GroupData* copy; + + orig = &groups[g]; + copy = &groups_copy[g]; + + copy->captures = &spans_copy[offset]; + offset += orig->count; + + if (orig->count > 0) { + Py_MEMCPY(copy->captures, orig->captures, orig->count * + sizeof(RE_GroupSpan)); + copy->capacity = orig->count; + copy->count = orig->count; + } + + copy->current = orig->current; + } + + return groups_copy; +} + +/* Makes a copy of a MatchObject. */ +Py_LOCAL_INLINE(PyObject*) make_match_copy(MatchObject* self) { + MatchObject* match; + + if (!self->string) { + /* The target string has been detached, so the MatchObject is now + * immutable. + */ + Py_INCREF(self); + return (PyObject*)self; + } + + /* Create a MatchObject. */ + match = PyObject_NEW(MatchObject, &Match_Type); + if (!match) + return NULL; + + match->string = self->string; + match->substring = self->substring; + match->substring_offset = self->substring_offset; + match->pattern = self->pattern; + match->pos = self->pos; + match->endpos = self->endpos; + match->match_start = self->match_start; + match->match_end = self->match_end; + match->lastindex = self->lastindex; + match->lastgroup = self->lastgroup; + match->group_count = self->group_count; + match->groups = NULL; /* Copy them later. */ + match->regs = self->regs; + Py_MEMCPY(match->fuzzy_counts, self->fuzzy_counts, + sizeof(self->fuzzy_counts)); + match->fuzzy_changes = NULL; /* Copy them later. */ + match->partial = self->partial; + Py_INCREF(match->string); + Py_INCREF(match->substring); + Py_INCREF(match->pattern); + Py_XINCREF(match->regs); + + /* Copy the groups to the MatchObject. */ + if (self->group_count > 0) { + match->groups = copy_groups(self->groups, self->group_count); + if (!match->groups) { + Py_DECREF(match); + return NULL; + } + } + + /* Copy the fuzzy changes to the MatchObject. */ + if (self->fuzzy_changes) { + size_t total_changes; + size_t size; + + total_changes = self->fuzzy_counts[RE_FUZZY_SUB] + + self->fuzzy_counts[RE_FUZZY_INS] + self->fuzzy_counts[RE_FUZZY_DEL]; + size = (size_t)total_changes * sizeof(RE_FuzzyChange); + match->fuzzy_changes = (RE_FuzzyChange*)re_alloc(size); + if (!match->fuzzy_changes) { + Py_DECREF(match); + return NULL; + } + Py_MEMCPY(match->fuzzy_changes, self->fuzzy_changes, size); + } + + return (PyObject*)match; +} + +/* Creates a new MatchObject. */ +Py_LOCAL_INLINE(PyObject*) pattern_new_match(PatternObject* pattern, RE_State* + state, int status) { + /* Create MatchObject (from state object). */ + if (status > 0 || status == RE_ERROR_PARTIAL) { + MatchObject* match; + + /* Create a MatchObject. */ + match = PyObject_NEW(MatchObject, &Match_Type); + if (!match) + return NULL; + + match->string = state->string; + match->substring = state->string; + match->substring_offset = 0; + match->pattern = pattern; + match->regs = NULL; + + if (pattern->is_fuzzy) + Py_MEMCPY(match->fuzzy_counts, state->fuzzy_counts, + sizeof(state->fuzzy_counts)); + else + memset(match->fuzzy_counts, 0, sizeof(match->fuzzy_counts)); + + if (state->fuzzy_changes.count > 0) { + size_t size; + + size = state->fuzzy_changes.count * sizeof(RE_FuzzyChange); + match->fuzzy_changes = (RE_FuzzyChange*)re_alloc(size); + if (!match->fuzzy_changes) { + Py_DECREF(match); + return NULL; + } + Py_MEMCPY(match->fuzzy_changes, state->fuzzy_changes.items, size); + } else + match->fuzzy_changes = NULL; + + match->partial = status == RE_ERROR_PARTIAL; + Py_INCREF(match->string); + Py_INCREF(match->substring); + Py_INCREF(match->pattern); + + /* Copy the groups to the MatchObject. */ + if (pattern->public_group_count > 0) { + match->groups = copy_groups(state->groups, + pattern->public_group_count); + if (!match->groups) { + Py_DECREF(match); + return NULL; + } + } else + match->groups = NULL; + + match->group_count = pattern->public_group_count; + + match->pos = state->slice_start; + match->endpos = state->slice_end; + + if (state->reverse) { + match->match_start = state->text_pos; + match->match_end = state->match_pos; + } else { + match->match_start = state->match_pos; + match->match_end = state->text_pos; + } + + match->lastindex = state->lastindex; + match->lastgroup = state->lastgroup; + + return (PyObject*)match; + } else if (status == 0) { + /* No match. */ + Py_RETURN_NONE; + } else { + /* Internal error. */ + set_error(status, NULL); + return NULL; + } +} + +/* Gets the text of a capture group from a state. */ +Py_LOCAL_INLINE(PyObject*) state_get_group(RE_State* state, Py_ssize_t index, + PyObject* string, BOOL empty) { + RE_GroupData* group; + Py_ssize_t start; + Py_ssize_t end; + + group = &state->groups[index - 1]; + + if (string != Py_None && index >= 1 && (size_t)index <= + state->pattern->public_group_count && group->current >= 0) { + RE_GroupSpan* span; + + span = &group->captures[group->current]; + start = span->start; + end = span->end; + } else if (empty) + /* Want an empty string. */ + start = end = 0; + else + Py_RETURN_NONE; + + return get_slice(string, start, end); +} + +/* Acquires the lock (mutex) on the state if there's one. + * + * It also increments the owner's refcount just to ensure that it won't be + * destroyed by another thread. + */ +Py_LOCAL_INLINE(void) acquire_state_lock(PyObject* owner, RE_State* state) { + if (state->lock) { + /* In order to avoid deadlock we need to release the GIL while trying + * to acquire the lock. + */ + Py_INCREF(owner); + if (!PyThread_acquire_lock(state->lock, 0)) { + release_GIL(state); + PyThread_acquire_lock(state->lock, 1); + acquire_GIL(state); + } + } +} + +/* Releases the lock (mutex) on the state if there's one. + * + * It also decrements the owner's refcount, which was incremented when the lock + * was acquired. + */ +Py_LOCAL_INLINE(void) release_state_lock(PyObject* owner, RE_State* state) { + if (state->lock) { + PyThread_release_lock(state->lock); + Py_DECREF(owner); + } +} + +/* Implements the functionality of ScanObject's search and match methods. */ +Py_LOCAL_INLINE(PyObject*) scanner_search_or_match(ScannerObject* self, BOOL + search) { + RE_State* state; + PyObject* match; + + state = &self->state; + + /* Acquire the state lock in case we're sharing the scanner object across + * threads. + */ + acquire_state_lock((PyObject*)self, state); + + if (self->status == RE_ERROR_FAILURE || self->status == RE_ERROR_PARTIAL) { + /* No or partial match. */ + release_state_lock((PyObject*)self, state); + Py_RETURN_NONE; + } else if (self->status < 0) { + /* Internal error. */ + release_state_lock((PyObject*)self, state); + set_error(self->status, NULL); + return NULL; + } + + /* Look for another match. */ + self->status = do_match(state, search); + if (self->status >= 0 || self->status == RE_ERROR_PARTIAL) { + /* Create the match object. */ + match = pattern_new_match(self->pattern, state, self->status); + + if (search && state->overlapped) { + /* Advance one character. */ + Py_ssize_t step; + + step = state->reverse ? -1 : 1; + state->text_pos = state->match_pos + step; + state->must_advance = FALSE; + } else + /* Don't allow 2 contiguous zero-width matches. */ + state->must_advance = state->text_pos == state->match_pos; + } else + /* Internal error. */ + match = NULL; + + /* Release the state lock. */ + release_state_lock((PyObject*)self, state); + + return match; +} + +/* ScannerObject's 'match' method. */ +static PyObject* scanner_match(ScannerObject* self, PyObject* unused) { + return scanner_search_or_match(self, FALSE); +} + +/* ScannerObject's 'search' method. */ +static PyObject* scanner_search(ScannerObject* self, PyObject* unused) { + return scanner_search_or_match(self, TRUE); +} + +/* Returns an iterator for a ScannerObject. + * + * The iterator is actually the ScannerObject itself. + */ +static PyObject* scanner_iter(PyObject* self) { + Py_INCREF(self); + return self; +} + +/* Gets the next result from a scanner iterator. */ +static PyObject* scanner_iternext(PyObject* self) { + PyObject* match; + + match = scanner_search((ScannerObject*)self, NULL); + + if (match == Py_None) { + /* No match. */ + Py_DECREF(match); + return NULL; + } + + return match; +} + +/* Makes a copy of a ScannerObject. + * + * It actually doesn't make a copy, just returns the original object. + */ +Py_LOCAL_INLINE(PyObject*) make_scanner_copy(ScannerObject* self) { + Py_INCREF(self); + return (PyObject*)self; +} + +/* ScannerObject's '__copy__' method. */ +static PyObject* scanner_copy(ScannerObject* self, PyObject* unused) { + return make_scanner_copy(self); +} + +/* ScannerObject's '__deepcopy__' method. */ +static PyObject* scanner_deepcopy(ScannerObject* self, PyObject* memo) { + return make_scanner_copy(self); +} + +/* The documentation of a ScannerObject. */ +PyDoc_STRVAR(scanner_match_doc, + "match() --> MatchObject or None.\n\ + Match at the current position in the string."); + +PyDoc_STRVAR(scanner_search_doc, + "search() --> MatchObject or None.\n\ + Search from the current position in the string."); + +/* ScannerObject's methods. */ +static PyMethodDef scanner_methods[] = { + {"match", (PyCFunction)scanner_match, METH_NOARGS, scanner_match_doc}, + {"search", (PyCFunction)scanner_search, METH_NOARGS, scanner_search_doc}, + {"__copy__", (PyCFunction)scanner_copy, METH_NOARGS}, + {"__deepcopy__", (PyCFunction)scanner_deepcopy, METH_O}, + {NULL, NULL} +}; + +PyDoc_STRVAR(scanner_doc, "Scanner object"); + +/* Deallocates a ScannerObject. */ +static void scanner_dealloc(PyObject* self_) { + ScannerObject* self; + + self = (ScannerObject*)self_; + + if (self->status != RE_ERROR_INITIALISING) + state_fini(&self->state); + Py_DECREF(self->pattern); + PyObject_DEL(self); +} + +static PyMemberDef scanner_members[] = { + {"pattern", T_OBJECT, offsetof(ScannerObject, pattern), READONLY, + "The regex object that produced this scanner object."}, + {NULL} /* Sentinel */ +}; + +static PyTypeObject Scanner_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "_regex.Scanner", + sizeof(ScannerObject) +}; + +/* Decodes a 'concurrent' argument. */ +Py_LOCAL_INLINE(int) decode_concurrent(PyObject* concurrent) { + Py_ssize_t value; + + if (concurrent == Py_None) + return RE_CONC_DEFAULT; + + value = PyLong_AsLong(concurrent); + if (value == -1 && PyErr_Occurred()) { + set_error(RE_ERROR_CONCURRENT, NULL); + return -1; + } + + return value ? RE_CONC_YES : RE_CONC_NO; +} + +/* Decodes a 'partial' argument. */ +Py_LOCAL_INLINE(BOOL) decode_partial(PyObject* partial) { + Py_ssize_t value; + + if (partial == Py_False) + return FALSE; + + if (partial == Py_True) + return TRUE; + + value = PyLong_AsLong(partial); + if (value == -1 && PyErr_Occurred()) { + PyErr_Clear(); + return TRUE; + } + + return value != 0; +} + +/* Decodes a 'timeout' argument. */ +Py_LOCAL_INLINE(Py_ssize_t) decode_timeout(PyObject* timeout) { + double value; + + if (timeout == Py_None) + return RE_NO_TIMEOUT; + + value = PyFloat_AsDouble(timeout); + if (value == -1.0 && PyErr_Occurred()) { + set_error(RE_ERROR_BAD_TIMEOUT, NULL); + return RE_BAD_TIMEOUT; + } + + return value >= 0.0 ? (Py_ssize_t)(value * CLOCKS_PER_SEC) : RE_NO_TIMEOUT; +} + +/* Creates a new ScannerObject. */ +static PyObject* pattern_scanner(PatternObject* pattern, PyObject* args, + PyObject* kwargs) { + /* Create search state object. */ + ScannerObject* self; + Py_ssize_t start; + Py_ssize_t end; + int conc; + Py_ssize_t tim; + BOOL part; + + PyObject* string; + PyObject* pos = Py_None; + PyObject* endpos = Py_None; + Py_ssize_t overlapped = FALSE; + PyObject* concurrent = Py_None; + PyObject* timeout = Py_None; + PyObject* partial = Py_False; + static char* kwlist[] = { "string", "pos", "endpos", "overlapped", + "concurrent", "partial", "timeout", NULL }; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOnOOO:scanner", kwlist, + &string, &pos, &endpos, &overlapped, &concurrent, &partial, &timeout)) + return NULL; + + start = as_string_index(pos, 0); + if (start == -1 && PyErr_Occurred()) + return NULL; + + end = as_string_index(endpos, PY_SSIZE_T_MAX); + if (end == -1 && PyErr_Occurred()) + return NULL; + + conc = decode_concurrent(concurrent); + if (conc < 0) + return NULL; + + tim = decode_timeout(timeout); + if (tim == RE_BAD_TIMEOUT) + return NULL; + + part = decode_partial(partial); + + /* Create a scanner object. */ + self = PyObject_NEW(ScannerObject, &Scanner_Type); + if (!self) + return NULL; + + self->pattern = pattern; + Py_INCREF(self->pattern); + self->status = RE_ERROR_INITIALISING; + + /* The MatchObject, and therefore repeated captures, will be visible. */ + if (!state_init(&self->state, pattern, string, start, end, overlapped != 0, + conc, part, TRUE, TRUE, FALSE, tim)) { + Py_DECREF(self); + return NULL; + } + + self->status = RE_ERROR_SUCCESS; + + return (PyObject*) self; +} + +/* Performs the split for the SplitterObject. */ +Py_LOCAL_INLINE(PyObject*) next_split_part(SplitterObject* self) { + RE_State* state; + PyObject* result = NULL; /* Initialise to stop compiler warning. */ + + state = &self->state; + + /* Acquire the state lock in case we're sharing the splitter object across + * threads. + */ + acquire_state_lock((PyObject*)self, state); + + if (self->status == RE_ERROR_FAILURE || self->status == RE_ERROR_PARTIAL) { + /* Finished. */ + release_state_lock((PyObject*)self, state); + result = Py_False; + Py_INCREF(result); + return result; + } else if (self->status < 0) { + /* Internal error. */ + release_state_lock((PyObject*)self, state); + set_error(self->status, NULL); + return NULL; + } + + if (self->index == 0) { + if (self->split_count < self->maxsplit) { + self->status = do_match(state, TRUE); + if (self->status < 0) + goto error; + + if (self->status == RE_ERROR_SUCCESS) { + ++self->split_count; + + /* Get segment before this match. */ + if (state->reverse) + result = get_slice(state->string, state->match_pos, + self->last_pos); + else + result = get_slice(state->string, self->last_pos, + state->match_pos); + if (!result) + goto error; + + self->last_pos = state->text_pos; + + /* Don't allow 2 contiguous zero-width matches. */ + state->must_advance = state->text_pos == state->match_pos; + } + } else + goto no_match; + + if (self->status == RE_ERROR_FAILURE || self->status == + RE_ERROR_PARTIAL) { +no_match: + /* Get segment following last match (even if empty). */ + if (state->reverse) + result = get_slice(state->string, 0, self->last_pos); + else + result = get_slice(state->string, self->last_pos, + state->text_length); + if (!result) + goto error; + } + } else { + /* Add group. */ + result = state_get_group(state, self->index, state->string, FALSE); + if (!result) + goto error; + } + + ++self->index; + if ((size_t)self->index > state->pattern->public_group_count) + self->index = 0; + + /* Release the state lock. */ + release_state_lock((PyObject*)self, state); + + return result; + +error: + /* Release the state lock. */ + release_state_lock((PyObject*)self, state); + + return NULL; +} + +/* SplitterObject's 'split' method. */ +static PyObject* splitter_split(SplitterObject* self, PyObject* unused) { + PyObject* result; + + result = next_split_part(self); + + if (result == Py_False) { + /* The sentinel. */ + Py_DECREF(Py_False); + Py_RETURN_NONE; + } + + return result; +} + +/* Returns an iterator for a SplitterObject. + * + * The iterator is actually the SplitterObject itself. + */ +static PyObject* splitter_iter(PyObject* self) { + Py_INCREF(self); + return self; +} + +/* Gets the next result from a splitter iterator. */ +static PyObject* splitter_iternext(PyObject* self) { + PyObject* result; + + result = next_split_part((SplitterObject*)self); + + if (result == Py_False) { + /* No match. */ + Py_DECREF(result); + return NULL; + } + + return result; +} + +/* Makes a copy of a SplitterObject. + * + * It actually doesn't make a copy, just returns the original object. + */ +Py_LOCAL_INLINE(PyObject*) make_splitter_copy(SplitterObject* self) { + Py_INCREF(self); + return (PyObject*)self; +} + +/* SplitterObject's '__copy__' method. */ +static PyObject* splitter_copy(SplitterObject* self, PyObject* unused) { + return make_splitter_copy(self); +} + +/* SplitterObject's '__deepcopy__' method. */ +static PyObject* splitter_deepcopy(SplitterObject* self, PyObject* memo) { + return make_splitter_copy(self); +} + +/* The documentation of a SplitterObject. */ +PyDoc_STRVAR(splitter_split_doc, + "split() --> string or None.\n\ + Return the next part of the split string."); + +/* SplitterObject's methods. */ +static PyMethodDef splitter_methods[] = { + {"split", (PyCFunction)splitter_split, METH_NOARGS, splitter_split_doc}, + {"__copy__", (PyCFunction)splitter_copy, METH_NOARGS}, + {"__deepcopy__", (PyCFunction)splitter_deepcopy, METH_O}, + {NULL, NULL} +}; + +PyDoc_STRVAR(splitter_doc, "Splitter object"); + +/* Deallocates a SplitterObject. */ +static void splitter_dealloc(PyObject* self_) { + SplitterObject* self; + + self = (SplitterObject*)self_; + + if (self->status != RE_ERROR_INITIALISING) + state_fini(&self->state); + Py_DECREF(self->pattern); + PyObject_DEL(self); +} + +/* Converts a captures index to an integer. + * + * A negative capture index in 'expandf' and 'subf' is passed as a string + * because negative indexes are not supported by 'str.format'. + */ +Py_LOCAL_INLINE(Py_ssize_t) index_to_integer(PyObject* item) { + Py_ssize_t value; + + value = PyLong_AsLong(item); + if (!(value == -1 && PyErr_Occurred())) + return value; + + PyErr_Clear(); + + /* Is the index a string representation of an integer? */ + if (PyUnicode_Check(item)) { + PyObject* int_obj; + + int_obj = PyLong_FromUnicodeObject(item, 0); + if (!int_obj) + goto error; + + value = PyLong_AsLong(int_obj); + Py_DECREF(int_obj); + if (!PyErr_Occurred()) + return value; + } else if (PyBytes_Check(item)) { + char* characters; + PyObject* int_obj; + + characters = PyBytes_AsString(item); + int_obj = PyLong_FromString(characters, NULL, 0); + if (!int_obj) + goto error; + + value = PyLong_AsLong(int_obj); + Py_DECREF(int_obj); + if (!PyErr_Occurred()) + return value; + } + +error: + PyErr_Clear(); + PyErr_Format(PyExc_TypeError, "list indices must be integers, not %.200s", + item->ob_type->tp_name); + + return -1; +} + +/* CaptureObject's length method. */ +Py_LOCAL_INLINE(Py_ssize_t) capture_length(CaptureObject* self) { + MatchObject* match; + RE_GroupData* group; + + if (self->group_index == 0) + return 1; + + match = *self->match_indirect; + group = &match->groups[self->group_index - 1]; + + return (Py_ssize_t)group->count; +} + +/* CaptureObject's '__getitem__' method. */ +static PyObject* capture_getitem(CaptureObject* self, PyObject* item) { + Py_ssize_t index; + MatchObject* match; + Py_ssize_t start; + Py_ssize_t end; + + index = index_to_integer(item); + if (index == -1 && PyErr_Occurred()) + return NULL; + + match = *self->match_indirect; + + if (self->group_index == 0) { + if (index < 0) + index += 1; + + if (index != 0) { + PyErr_SetString(PyExc_IndexError, "list index out of range"); + return NULL; + } + + start = match->match_start; + end = match->match_end; + } else { + RE_GroupData* group; + RE_GroupSpan* span; + + group = &match->groups[self->group_index - 1]; + + if (index < 0) + index += (Py_ssize_t)group->count; + + if (index < 0 || index >= (Py_ssize_t)group->count) { + PyErr_SetString(PyExc_IndexError, "list index out of range"); + return NULL; + } + + span = &group->captures[index]; + + start = span->start; + end = span->end; + } + + return get_slice(match->substring, start - match->substring_offset, end - + match->substring_offset); +} + +static PyMappingMethods capture_as_mapping = { + (lenfunc)capture_length, /* mp_length */ + (binaryfunc)capture_getitem, /* mp_subscript */ + 0, /* mp_ass_subscript */ +}; + +/* CaptureObject's methods. */ +static PyMethodDef capture_methods[] = { + {"__getitem__", (PyCFunction)capture_getitem, METH_O|METH_COEXIST}, + {NULL, NULL} +}; + +/* Deallocates a CaptureObject. */ +static void capture_dealloc(PyObject* self_) { + CaptureObject* self; + + self = (CaptureObject*)self_; + PyObject_DEL(self); +} + +/* CaptureObject's 'str' method. */ +static PyObject* capture_str(PyObject* self_) { + CaptureObject* self; + MatchObject* match; + PyObject* default_value; + PyObject* result; + + self = (CaptureObject*)self_; + match = *self->match_indirect; + + default_value = PySequence_GetSlice(match->string, 0, 0); + result = match_get_group_by_index(match, self->group_index, default_value); + Py_DECREF(default_value); + + return result; +} + +static PyMemberDef splitter_members[] = { + {"pattern", T_OBJECT, offsetof(SplitterObject, pattern), READONLY, + "The regex object that produced this splitter object."}, + {NULL} /* Sentinel */ +}; + +static PyTypeObject Splitter_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "_regex.Splitter", + sizeof(SplitterObject) +}; + +/* Creates a new SplitterObject. */ +Py_LOCAL_INLINE(PyObject*) pattern_splitter(PatternObject* pattern, PyObject* + args, PyObject* kwargs) { + /* Create split state object. */ + int conc; + Py_ssize_t tim; + SplitterObject* self; + + PyObject* string; + Py_ssize_t maxsplit = 0; + PyObject* concurrent = Py_None; + PyObject* timeout = Py_None; + static char* kwlist[] = { "string", "maxsplit", "concurrent", "timeout", + NULL }; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|nOO:splitter", kwlist, + &string, &maxsplit, &concurrent, &timeout)) + return NULL; + + conc = decode_concurrent(concurrent); + if (conc < 0) + return NULL; + + tim = decode_timeout(timeout); + if (tim == RE_BAD_TIMEOUT) + return NULL; + + /* Create a splitter object. */ + self = PyObject_NEW(SplitterObject, &Splitter_Type); + if (!self) + return NULL; + + self->pattern = pattern; + Py_INCREF(self->pattern); + self->status = RE_ERROR_INITIALISING; + + if (maxsplit == 0) + maxsplit = PY_SSIZE_T_MAX; + + /* The MatchObject, and therefore repeated captures, will not be visible. + */ + if (!state_init(&self->state, pattern, string, 0, PY_SSIZE_T_MAX, FALSE, + conc, FALSE, TRUE, FALSE, FALSE, tim)) { + Py_DECREF(self); + return NULL; + } + + self->maxsplit = maxsplit; + self->last_pos = self->state.reverse ? self->state.text_length : 0; + self->split_count = 0; + self->index = 0; + self->status = RE_ERROR_SUCCESS; + + return (PyObject*) self; +} + +/* Implements the functionality of PatternObject's search and match methods. */ +Py_LOCAL_INLINE(PyObject*) pattern_search_or_match(PatternObject* self, + PyObject* args, PyObject* kwargs, char* args_desc, BOOL search, BOOL + match_all) { + Py_ssize_t start; + Py_ssize_t end; + int conc; + Py_ssize_t tim; + BOOL part; + RE_State state; + int status; + PyObject* match; + + PyObject* string; + PyObject* pos = Py_None; + PyObject* endpos = Py_None; + PyObject* concurrent = Py_None; + PyObject* timeout = Py_None; + PyObject* partial = Py_False; + static char* kwlist[] = { "string", "pos", "endpos", "concurrent", + "partial", "timeout", NULL }; + /* When working with a short string, such as a line from a file, the + * relative cost of PyArg_ParseTupleAndKeywords can be significant, and + * it's worth not using it when there are only positional arguments. + */ + Py_ssize_t arg_count; + if (args && !kwargs && PyTuple_CheckExact(args)) + arg_count = PyTuple_GET_SIZE(args); + else + arg_count = -1; + + if (1 <= arg_count && arg_count <= 5) { + /* PyTuple_GET_ITEM borrows the reference. */ + string = PyTuple_GET_ITEM(args, 0); + if (arg_count >= 2) + pos = PyTuple_GET_ITEM(args, 1); + if (arg_count >= 3) + endpos = PyTuple_GET_ITEM(args, 2); + if (arg_count >= 4) + concurrent = PyTuple_GET_ITEM(args, 3); + if (arg_count >= 5) + partial = PyTuple_GET_ITEM(args, 4); + if (arg_count >= 6) + timeout = PyTuple_GET_ITEM(args, 5); + } else if (!PyArg_ParseTupleAndKeywords(args, kwargs, args_desc, kwlist, + &string, &pos, &endpos, &concurrent, &partial, &timeout)) + return NULL; + + start = as_string_index(pos, 0); + if (start == -1 && PyErr_Occurred()) + return NULL; + + end = as_string_index(endpos, PY_SSIZE_T_MAX); + if (end == -1 && PyErr_Occurred()) + return NULL; + + conc = decode_concurrent(concurrent); + if (conc < 0) + return NULL; + + tim = decode_timeout(timeout); + if (tim == RE_BAD_TIMEOUT) + return NULL; + + part = decode_partial(partial); + + /* The MatchObject, and therefore repeated captures, will be visible. */ + if (!state_init(&state, self, string, start, end, FALSE, conc, part, FALSE, + TRUE, match_all, tim)) + return NULL; + + status = do_match(&state, search); + + if (status >= 0 || status == RE_ERROR_PARTIAL) + /* Create the match object. */ + match = pattern_new_match(self, &state, status); + else + match = NULL; + + state_fini(&state); + + return match; +} + +/* PatternObject's 'match' method. */ +static PyObject* pattern_match(PatternObject* self, PyObject* args, PyObject* + kwargs) { + return pattern_search_or_match(self, args, kwargs, "O|OOOOO:match", FALSE, + FALSE); +} + +/* PatternObject's 'fullmatch' method. */ +static PyObject* pattern_fullmatch(PatternObject* self, PyObject* args, + PyObject* kwargs) { + return pattern_search_or_match(self, args, kwargs, "O|OOOOO:fullmatch", + FALSE, TRUE); +} + +/* PatternObject's 'search' method. */ +static PyObject* pattern_search(PatternObject* self, PyObject* args, PyObject* + kwargs) { + return pattern_search_or_match(self, args, kwargs, "O|OOOOO:search", TRUE, + FALSE); +} + +/* Gets the limits of the matching. */ +Py_LOCAL_INLINE(BOOL) get_limits(PyObject* pos, PyObject* endpos, Py_ssize_t + length, Py_ssize_t* start, Py_ssize_t* end) { + Py_ssize_t s; + Py_ssize_t e; + + s = as_string_index(pos, 0); + if (s == -1 && PyErr_Occurred()) + return FALSE; + + e = as_string_index(endpos, PY_SSIZE_T_MAX); + if (e == -1 && PyErr_Occurred()) + return FALSE; + + /* Adjust boundaries. */ + if (s < 0) + s += length; + if (s < 0) + s = 0; + else if (s > length) + s = length; + + if (e < 0) + e += length; + if (e < 0) + e = 0; + else if (e > length) + e = length; + + *start = s; + *end = e; + + return TRUE; +} + +/* Gets a replacement item from the replacement list. + * + * The replacement item could be a string literal or a group. + * + * It can return None to represent an empty string. + */ +Py_LOCAL_INLINE(PyObject*) get_sub_replacement(PyObject* item, PyObject* + string, RE_State* state, size_t group_count) { + Py_ssize_t index; + + if (PyUnicode_CheckExact(item) || PyBytes_CheckExact(item)) { + /* It's a literal, which can be added directly to the list. */ + + /* ensure_immutable will DECREF the original item if it has to make an + * immutable copy, but that original item might have a borrowed + * reference, so we must INCREF it first in order to ensure it won't be + * destroyed. + */ + Py_INCREF(item); + item = ensure_immutable(item); + return item; + } + + /* Is it a group reference? */ + index = as_group_index(item); + if (index == -1 && PyErr_Occurred()) { + /* Not a group either! */ + set_error(RE_ERROR_REPLACEMENT, NULL); + return NULL; + } + + if (index == 0) { + /* The entire matched portion of the string. */ + if (state->match_pos == state->text_pos) { + /* Return None for "". */ + Py_RETURN_NONE; + } + + if (state->reverse) + return get_slice(string, state->text_pos, state->match_pos); + else + return get_slice(string, state->match_pos, state->text_pos); + } else if (1 <= index && (size_t)index <= group_count) { + /* A group. */ + RE_GroupData* group; + RE_GroupSpan* span; + + group = &state->groups[index - 1]; + + if (group->current < 0) { + /* The group didn't match or is "", so return None for "". */ + Py_RETURN_NONE; + } + + span = &group->captures[group->current]; + + return get_slice(string, span->start, span->end); + } else { + /* No such group. */ + set_error(RE_ERROR_INVALID_GROUP_REF, NULL); + return NULL; + } +} + +/* PatternObject's 'subx' method. */ +Py_LOCAL_INLINE(PyObject*) pattern_subx(PatternObject* self, PyObject* + str_template, PyObject* string, Py_ssize_t maxsub, int sub_type, PyObject* + pos, PyObject* endpos, int concurrent, Py_ssize_t timeout) { + RE_StringInfo str_info; + Py_ssize_t start; + Py_ssize_t end; + BOOL is_callable = FALSE; + PyObject* replacement = NULL; + BOOL is_literal = FALSE; + BOOL is_format = FALSE; + BOOL is_template = FALSE; + RE_State state; + RE_JoinInfo join_info; + Py_ssize_t sub_count; + Py_ssize_t last_pos; + PyObject* item; + MatchObject* match; + BOOL built_capture = FALSE; + PyObject* args = NULL; + PyObject* kwargs = NULL; + Py_ssize_t end_pos; + + /* Get the string. */ + if (!get_string(string, &str_info)) + return NULL; + + if (!check_compatible(self, str_info.is_unicode)) { + release_buffer(&str_info); + return NULL; + } + + /* Get the limits of the search. */ + if (!get_limits(pos, endpos, str_info.length, &start, &end)) { + release_buffer(&str_info); + return NULL; + } + + /* If the pattern is too long for the string, then take a shortcut, unless + * it's a fuzzy pattern. + */ + if (!self->is_fuzzy && self->min_width > end - start) { + PyObject* result; + + Py_INCREF(string); + + if (sub_type & RE_SUBN) + result = Py_BuildValue("Nn", string, 0); + else + result = string; + + release_buffer(&str_info); + + return result; + } + + if (maxsub == 0) + maxsub = PY_SSIZE_T_MAX; + + /* sub/subn takes either a function or a string template. */ + if (PyCallable_Check(str_template)) { + /* It's callable. */ + is_callable = TRUE; + + replacement = str_template; + Py_INCREF(replacement); + } else if (sub_type & RE_SUBF) { + /* Is it a literal format? + * + * To keep it simple we'll say that a literal is a string which can be + * used as-is, so no placeholders. + */ + Py_ssize_t literal_length; + + literal_length = check_replacement_string(str_template, '{'); + if (literal_length > 0) { + /* It's a literal. */ + is_literal = TRUE; + + replacement = str_template; + Py_INCREF(replacement); + } else if (literal_length < 0) { + /* It isn't a literal, so get the 'format' method. */ + is_format = TRUE; + + replacement = PyObject_GetAttrString(str_template, "format"); + if (!replacement) { + release_buffer(&str_info); + return NULL; + } + } + } else { + /* Is it a literal template? + * + * To keep it simple we'll say that a literal is a string which can be + * used as-is, so no backslashes. + */ + Py_ssize_t literal_length; + + literal_length = check_replacement_string(str_template, '\\'); + if (literal_length > 0) { + /* It's a literal. */ + is_literal = TRUE; + + replacement = str_template; + Py_INCREF(replacement); + } else if (literal_length < 0 ) { + /* It isn't a literal, so hand it over to the template compiler. */ + is_template = TRUE; + + replacement = call("regex.regex", "_compile_replacement_helper", + PyTuple_Pack(2, self, str_template)); + if (!replacement) { + release_buffer(&str_info); + return NULL; + } + } + } + + /* The MatchObject, and therefore repeated captures, will be visible only + * if the replacement is callable or subf is used. + */ + if (!state_init_2(&state, self, string, &str_info, start, end, FALSE, + concurrent, FALSE, FALSE, is_callable || (sub_type & RE_SUBF) != 0, + FALSE, timeout)) { + release_buffer(&str_info); + Py_XDECREF(replacement); + return NULL; + } + + init_join_list(&join_info, state.reverse, PyUnicode_Check(string)); + + sub_count = 0; + last_pos = state.reverse ? state.text_length : 0; + while (sub_count < maxsub) { + int status; + + status = do_match(&state, TRUE); + if (status < 0) + goto error; + + if (status == 0) + break; + + /* Append the segment before this match. */ + if (state.match_pos != last_pos) { + if (state.reverse) + item = get_slice(string, state.match_pos, last_pos); + else + item = get_slice(string, last_pos, state.match_pos); + if (!item) + goto error; + + /* Add to the list. */ + status = add_to_join_list(&join_info, item); + Py_DECREF(item); + if (status < 0) + goto error; + } + + /* Add this match. */ + if (is_literal) { + /* The replacement is a literal string. */ + status = add_to_join_list(&join_info, replacement); + if (status < 0) + goto error; + } else if (is_format) { + /* The replacement is a format string. */ + size_t g; + + /* We need to create the arguments for the 'format' method. We'll + * start by creating a MatchObject. + */ + match = (MatchObject*)pattern_new_match(self, &state, 1); + if (!match) + goto error; + + /* We'll build the args and kwargs the first time. They'll be using + * capture objects which refer to the match object indirectly; this + * means that args and kwargs can be reused with different match + * objects. + */ + if (!built_capture) { + /* The args are a tuple of the capture group matches. */ + args = PyTuple_New((Py_ssize_t)match->group_count + 1); + if (!args) { + Py_DECREF(match); + goto error; + } + + for (g = 0; g < match->group_count + 1; g++) + /* PyTuple_SetItem borrows the reference. */ + PyTuple_SetItem(args, (Py_ssize_t)g, + make_capture_object(&match, (Py_ssize_t)g)); + + /* The kwargs are a dict of the named capture group matches. */ + kwargs = make_capture_dict(match, &match); + if (!kwargs) { + Py_DECREF(args); + Py_DECREF(match); + goto error; + } + + built_capture = TRUE; + } + + /* Call the 'format' method. */ + item = PyObject_Call(replacement, args, kwargs); + + Py_DECREF(match); + if (!item) + goto error; + + /* Add the result to the list. */ + status = add_to_join_list(&join_info, item); + Py_DECREF(item); + if (status < 0) + goto error; + } else if (is_template) { + /* The replacement is a list template. */ + Py_ssize_t count; + Py_ssize_t index; + Py_ssize_t step; + + /* Add each part of the template to the list. */ + count = PyList_Size(replacement); + if (join_info.reversed) { + /* We're searching backwards, so we'll be reversing the list + * when it's complete. Therefore, we need to add the items of + * the template in reverse order for them to be in the correct + * order after the reversal. + */ + index = count - 1; + step = -1; + } else { + /* We're searching forwards. */ + index = 0; + step = 1; + } + + while (count > 0) { + PyObject* item; + PyObject* str_item; + + /* PyList_GetItem borrows a reference. */ + item = PyList_GetItem(replacement, index); + str_item = get_sub_replacement(item, string, &state, + self->public_group_count); + if (!str_item) + goto error; + + /* Add the result to the list. */ + if (str_item == Py_None) + /* None for "". */ + Py_DECREF(str_item); + else { + status = add_to_join_list(&join_info, str_item); + Py_DECREF(str_item); + if (status < 0) + goto error; + } + + --count; + index += step; + } + } else if (is_callable) { + /* Pass a MatchObject to the replacement function. */ + PyObject* match; + PyObject* args; + + /* We need to create a MatchObject to pass to the replacement + * function. + */ + match = pattern_new_match(self, &state, 1); + if (!match) + goto error; + + /* The args for the replacement function. */ + args = PyTuple_Pack(1, match); + if (!args) { + Py_DECREF(match); + goto error; + } + + /* Call the replacement function. */ + item = PyObject_CallObject(replacement, args); + Py_DECREF(args); + Py_DECREF(match); + if (!item) + goto error; + + /* Add the result to the list. */ + if (item != Py_None) + status = add_to_join_list(&join_info, item); + + Py_DECREF(item); + if (status < 0) + goto error; + } + + ++sub_count; + + last_pos = state.text_pos; + + /* Don't allow 2 contiguous zero-width matches. */ + state.must_advance = state.match_pos == state.text_pos; + } + + /* Get the segment following the last match. We use 'length' instead of + * 'text_length' because the latter is truncated to 'slice_end', a + * documented idiosyncracy of the 're' module. + */ + end_pos = state.reverse ? 0 : str_info.length; + if (last_pos != end_pos) { + int status; + + /* The segment is part of the original string. */ + if (state.reverse) + item = get_slice(string, 0, last_pos); + else + item = get_slice(string, last_pos, str_info.length); + if (!item) + goto error; + + status = add_to_join_list(&join_info, item); + Py_DECREF(item); + if (status < 0) + goto error; + } + + Py_XDECREF(replacement); + + /* Convert the list to a single string (also cleans up join_info). */ + item = join_list_info(&join_info); + + state_fini(&state); + + if (built_capture) { + Py_DECREF(kwargs); + Py_DECREF(args); + } + + if (!item) + return NULL; + + if (sub_type & RE_SUBN) + return Py_BuildValue("Nn", item, sub_count); + + return item; + +error: + if (built_capture) { + Py_DECREF(kwargs); + Py_DECREF(args); + } + + clear_join_list(&join_info); + state_fini(&state); + Py_XDECREF(replacement); + return NULL; +} + +/* PatternObject's 'sub' method. */ +static PyObject* pattern_sub(PatternObject* self, PyObject* args, PyObject* + kwargs) { + int conc; + Py_ssize_t tim; + + PyObject* replacement; + PyObject* string; + Py_ssize_t count = 0; + PyObject* pos = Py_None; + PyObject* endpos = Py_None; + PyObject* concurrent = Py_None; + PyObject* timeout = Py_None; + static char* kwlist[] = { "repl", "string", "count", "pos", "endpos", + "concurrent", "timeout", NULL }; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|nOOOO:sub", kwlist, + &replacement, &string, &count, &pos, &endpos, &concurrent, &timeout)) + return NULL; + + conc = decode_concurrent(concurrent); + if (conc < 0) + return NULL; + + tim = decode_timeout(timeout); + if (tim == RE_BAD_TIMEOUT) + return NULL; + + return pattern_subx(self, replacement, string, count, RE_SUB, pos, endpos, + conc, tim); +} + +/* PatternObject's 'subf' method. */ +static PyObject* pattern_subf(PatternObject* self, PyObject* args, PyObject* + kwargs) { + int conc; + Py_ssize_t tim; + + PyObject* format; + PyObject* string; + Py_ssize_t count = 0; + PyObject* pos = Py_None; + PyObject* endpos = Py_None; + PyObject* concurrent = Py_None; + PyObject* timeout = Py_None; + static char* kwlist[] = { "format", "string", "count", "pos", "endpos", + "concurrent", "timeout", NULL }; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|nOOOO:sub", kwlist, + &format, &string, &count, &pos, &endpos, &concurrent, &timeout)) + return NULL; + + conc = decode_concurrent(concurrent); + if (conc < 0) + return NULL; + + tim = decode_timeout(timeout); + if (tim == RE_BAD_TIMEOUT) + return NULL; + + return pattern_subx(self, format, string, count, RE_SUBF, pos, endpos, + conc, tim); +} + +/* PatternObject's 'subn' method. */ +static PyObject* pattern_subn(PatternObject* self, PyObject* args, PyObject* + kwargs) { + int conc; + Py_ssize_t tim; + + PyObject* replacement; + PyObject* string; + Py_ssize_t count = 0; + PyObject* pos = Py_None; + PyObject* endpos = Py_None; + PyObject* concurrent = Py_None; + PyObject* timeout = Py_None; + static char* kwlist[] = { "repl", "string", "count", "pos", "endpos", + "concurrent", "timeout", NULL }; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|nOOOO:subn", kwlist, + &replacement, &string, &count, &pos, &endpos, &concurrent, &timeout)) + return NULL; + + conc = decode_concurrent(concurrent); + if (conc < 0) + return NULL; + + tim = decode_timeout(timeout); + if (tim == RE_BAD_TIMEOUT) + return NULL; + + return pattern_subx(self, replacement, string, count, RE_SUBN, pos, endpos, + conc, tim); +} + +/* PatternObject's 'subfn' method. */ +static PyObject* pattern_subfn(PatternObject* self, PyObject* args, PyObject* + kwargs) { + int conc; + Py_ssize_t tim; + + PyObject* format; + PyObject* string; + Py_ssize_t count = 0; + PyObject* pos = Py_None; + PyObject* endpos = Py_None; + PyObject* concurrent = Py_None; + PyObject* timeout = Py_None; + static char* kwlist[] = { "format", "string", "count", "pos", "endpos", + "concurrent", "timeout", NULL }; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|nOOOO:subn", kwlist, + &format, &string, &count, &pos, &endpos, &concurrent, &timeout)) + return NULL; + + conc = decode_concurrent(concurrent); + if (conc < 0) + return NULL; + + tim = decode_timeout(timeout); + if (tim == RE_BAD_TIMEOUT) + return NULL; + + return pattern_subx(self, format, string, count, RE_SUBF | RE_SUBN, pos, + endpos, conc, tim); +} + +/* PatternObject's 'split' method. */ +static PyObject* pattern_split(PatternObject* self, PyObject* args, PyObject* + kwargs) { + int conc; + Py_ssize_t tim; + RE_State state; + PyObject* list; + PyObject* item; + int status; + Py_ssize_t split_count; + size_t g; + Py_ssize_t start_pos; + Py_ssize_t last_pos; + + PyObject* string; + Py_ssize_t maxsplit = 0; + PyObject* concurrent = Py_None; + PyObject* timeout = Py_None; + static char* kwlist[] = { "string", "maxsplit", "concurrent", "timeout", + NULL }; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|nOO:split", kwlist, + &string, &maxsplit, &concurrent, &timeout)) + return NULL; + + if (maxsplit == 0) + maxsplit = PY_SSIZE_T_MAX; + + conc = decode_concurrent(concurrent); + if (conc < 0) + return NULL; + + tim = decode_timeout(timeout); + if (tim == RE_BAD_TIMEOUT) + return NULL; + + /* The MatchObject, and therefore repeated captures, will not be visible. + */ + if (!state_init(&state, self, string, 0, PY_SSIZE_T_MAX, FALSE, conc, + FALSE, FALSE, FALSE, FALSE, tim)) + return NULL; + + list = PyList_New(0); + if (!list) { + state_fini(&state); + return NULL; + } + + split_count = 0; + if (state.reverse) { + start_pos = state.text_length; + } else { + start_pos = 0; + } + + last_pos = start_pos; + while (split_count < maxsplit) { + status = do_match(&state, TRUE); + if (status < 0) + goto error; + + if (status == 0) + /* No more matches. */ + break; + + /* Get segment before this match. */ + if (state.reverse) + item = get_slice(string, state.match_pos, last_pos); + else + item = get_slice(string, last_pos, state.match_pos); + if (!item) + goto error; + + status = PyList_Append(list, item); + Py_DECREF(item); + if (status < 0) + goto error; + + /* Add groups (if any). */ + for (g = 1; g <= self->public_group_count; g++) { + item = state_get_group(&state, (Py_ssize_t)g, string, FALSE); + if (!item) + goto error; + + status = PyList_Append(list, item); + Py_DECREF(item); + if (status < 0) + goto error; + } + + ++split_count; + last_pos = state.text_pos; + + /* Don't allow 2 contiguous zero-width matches. */ + state.must_advance = state.text_pos == state.match_pos; + } + + /* Get segment following last match (even if empty). */ + if (state.reverse) + item = get_slice(string, 0, last_pos); + else + item = get_slice(string, last_pos, state.text_length); + if (!item) + goto error; + + status = PyList_Append(list, item); + Py_DECREF(item); + if (status < 0) + goto error; + + state_fini(&state); + + return list; + +error: + Py_DECREF(list); + state_fini(&state); + return NULL; +} + +/* PatternObject's 'splititer' method. */ +static PyObject* pattern_splititer(PatternObject* pattern, PyObject* args, + PyObject* kwargs) { + return pattern_splitter(pattern, args, kwargs); +} + +/* PatternObject's 'findall' method. */ +static PyObject* pattern_findall(PatternObject* self, PyObject* args, PyObject* + kwargs) { + Py_ssize_t start; + Py_ssize_t end; + int conc; + Py_ssize_t tim; + RE_State state; + PyObject* list; + Py_ssize_t step; + int status; + Py_ssize_t b; + Py_ssize_t e; + size_t g; + + PyObject* string; + PyObject* pos = Py_None; + PyObject* endpos = Py_None; + Py_ssize_t overlapped = FALSE; + PyObject* concurrent = Py_None; + PyObject* timeout = Py_None; + static char* kwlist[] = { "string", "pos", "endpos", "overlapped", + "concurrent", "timeout", NULL }; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOnOO:findall", kwlist, + &string, &pos, &endpos, &overlapped, &concurrent, &timeout)) + return NULL; + + start = as_string_index(pos, 0); + if (start == -1 && PyErr_Occurred()) + return NULL; + + end = as_string_index(endpos, PY_SSIZE_T_MAX); + if (end == -1 && PyErr_Occurred()) + return NULL; + + conc = decode_concurrent(concurrent); + if (conc < 0) + return NULL; + + tim = decode_timeout(timeout); + if (tim == RE_BAD_TIMEOUT) + return NULL; + + /* The MatchObject, and therefore repeated captures, will not be visible. + */ + if (!state_init(&state, self, string, start, end, overlapped != 0, conc, + FALSE, FALSE, FALSE, FALSE, tim)) + return NULL; + + list = PyList_New(0); + if (!list) { + state_fini(&state); + return NULL; + } + + step = state.reverse ? -1 : 1; + while (state.slice_start <= state.text_pos && state.text_pos <= + state.slice_end) { + PyObject* item; + + status = do_match(&state, TRUE); + if (status < 0) + goto error; + + if (status == 0) + break; + + /* Don't bother to build a MatchObject. */ + switch (self->visible_capture_count) { + case 0: + if (state.reverse) { + b = state.text_pos; + e = state.match_pos; + } else { + b = state.match_pos; + e = state.text_pos; + } + item = get_slice(string, b, e); + if (!item) + goto error; + break; + case 1: + item = state_get_group(&state, 1, string, TRUE); + if (!item) + goto error; + break; + default: + item = PyTuple_New((Py_ssize_t)self->public_group_count); + if (!item) + goto error; + + for (g = 0; g < self->public_group_count; g++) { + PyObject* o; + + o = state_get_group(&state, (Py_ssize_t)g + 1, string, TRUE); + if (!o) { + Py_DECREF(item); + goto error; + } + + /* PyTuple_SET_ITEM borrows the reference. */ + PyTuple_SET_ITEM(item, g, o); + } + break; + } + + status = PyList_Append(list, item); + Py_DECREF(item); + if (status < 0) + goto error; + + if (state.overlapped) { + /* Advance one character. */ + state.text_pos = state.match_pos + step; + state.must_advance = FALSE; + } else + /* Don't allow 2 contiguous zero-width matches. */ + state.must_advance = state.text_pos == state.match_pos; + } + + state_fini(&state); + + return list; + +error: + Py_DECREF(list); + state_fini(&state); + return NULL; +} + +/* PatternObject's 'finditer' method. */ +static PyObject* pattern_finditer(PatternObject* pattern, PyObject* args, + PyObject* kwargs) { + return pattern_scanner(pattern, args, kwargs); +} + +/* Makes a copy of a PatternObject. + * + * It actually doesn't make a copy, just returns the original object. + */ +Py_LOCAL_INLINE(PyObject*) make_pattern_copy(PatternObject* self) { + Py_INCREF(self); + return (PyObject*)self; +} + +/* PatternObject's '__copy__' method. */ +static PyObject* pattern_copy(PatternObject* self, PyObject* unused) { + return make_pattern_copy(self); +} + +/* PatternObject's '__deepcopy__' method. */ +static PyObject* pattern_deepcopy(PatternObject* self, PyObject* memo) { + return make_pattern_copy(self); +} + +/* PatternObject's '__sizeof__' method. */ +static PyObject* pattern_sizeof(PatternObject* self, PyObject* args) { + Py_ssize_t size; + size_t i; + PyObject* result; + + size = sizeof(PatternObject); + size += self->node_count * sizeof(RE_Node); + + for (i = 0; i < self->node_count; i++) { + RE_Node* node; + + node = self->node_list[i]; + size += node->value_count * sizeof(RE_CODE); + } + + size += self->true_group_count * sizeof(RE_GroupInfo); + size += self->repeat_count * sizeof(RE_RepeatInfo); + + result = PyObject_CallMethod(self->packed_code_list, "__sizeof__", NULL); + if (!result) + return NULL; + + size += PyLong_AsSize_t(result); + Py_DECREF(result); + + size += self->call_ref_info_count * sizeof(RE_CallRefInfo); + + if (self->locale_info) + size += sizeof(RE_LocaleInfo); + + return PyLong_FromSsize_t(size); +} + +/* The documentation of a PatternObject. */ +PyDoc_STRVAR(pattern_match_doc, + "match(string, pos=None, endpos=None, concurrent=None, timeout=None) --> MatchObject or None.\n\ + Match zero or more characters at the beginning of the string."); + +PyDoc_STRVAR(pattern_fullmatch_doc, + "fullmatch(string, pos=None, endpos=None, concurrent=None, timeout=None) --> MatchObject or None.\n\ + Match zero or more characters against all of the string."); + +PyDoc_STRVAR(pattern_search_doc, + "search(string, pos=None, endpos=None, concurrent=None, timeout=None) --> MatchObject or None.\n\ + Search through string looking for a match, and return a corresponding\n\ + match object instance. Return None if no match is found."); + +PyDoc_STRVAR(pattern_sub_doc, + "sub(repl, string, count=0, flags=0, pos=None, endpos=None, concurrent=None, timeout=None) --> newstring\n\ + Return the string obtained by replacing the leftmost (or rightmost with a\n\ + reverse pattern) non-overlapping occurrences of pattern in string by the\n\ + replacement repl."); + +PyDoc_STRVAR(pattern_subf_doc, + "subf(format, string, count=0, flags=0, pos=None, endpos=None, concurrent=None, timeout=None) --> newstring\n\ + Return the string obtained by replacing the leftmost (or rightmost with a\n\ + reverse pattern) non-overlapping occurrences of pattern in string by the\n\ + replacement format."); + +PyDoc_STRVAR(pattern_subn_doc, + "subn(repl, string, count=0, flags=0, pos=None, endpos=None, concurrent=None, timeout=None) --> (newstring, number of subs)\n\ + Return the tuple (new_string, number_of_subs_made) found by replacing the\n\ + leftmost (or rightmost with a reverse pattern) non-overlapping occurrences\n\ + of pattern with the replacement repl."); + +PyDoc_STRVAR(pattern_subfn_doc, + "subfn(format, string, count=0, flags=0, pos=None, endpos=None, concurrent=None, timeout=None) --> (newstring, number of subs)\n\ + Return the tuple (new_string, number_of_subs_made) found by replacing the\n\ + leftmost (or rightmost with a reverse pattern) non-overlapping occurrences\n\ + of pattern with the replacement format."); + +PyDoc_STRVAR(pattern_split_doc, + "split(string, maxsplit=0, concurrent=None, timeout=None) --> list.\n\ + Split string by the occurrences of pattern."); + +PyDoc_STRVAR(pattern_splititer_doc, + "splititer(string, maxsplit=0, concurrent=None, timeout=None) --> iterator.\n\ + Return an iterator yielding the parts of a split string."); + +PyDoc_STRVAR(pattern_findall_doc, + "findall(string, pos=None, endpos=None, overlapped=False, concurrent=None, timeout=None) --> list.\n\ + Return a list of all matches of pattern in string. The matches may be\n\ + overlapped if overlapped is True."); + +PyDoc_STRVAR(pattern_finditer_doc, + "finditer(string, pos=None, endpos=None, overlapped=False, concurrent=None, timeout=None) --> iterator.\n\ + Return an iterator over all matches for the RE pattern in string. The\n\ + matches may be overlapped if overlapped is True. For each match, the\n\ + iterator returns a MatchObject."); + +PyDoc_STRVAR(pattern_scanner_doc, + "scanner(string, pos=None, endpos=None, overlapped=False, concurrent=None, timeout=None) --> scanner.\n\ + Return an scanner for the RE pattern in string. The matches may be overlapped\n\ + if overlapped is True."); + +/* The methods of a PatternObject. */ +static PyMethodDef pattern_methods[] = { + {"match", (PyCFunction)pattern_match, METH_VARARGS|METH_KEYWORDS, + pattern_match_doc}, + {"fullmatch", (PyCFunction)pattern_fullmatch, METH_VARARGS|METH_KEYWORDS, + pattern_fullmatch_doc}, + {"search", (PyCFunction)pattern_search, METH_VARARGS|METH_KEYWORDS, + pattern_search_doc}, + {"sub", (PyCFunction)pattern_sub, METH_VARARGS|METH_KEYWORDS, + pattern_sub_doc}, + {"subf", (PyCFunction)pattern_subf, METH_VARARGS|METH_KEYWORDS, + pattern_subf_doc}, + {"subn", (PyCFunction)pattern_subn, METH_VARARGS|METH_KEYWORDS, + pattern_subn_doc}, + {"subfn", (PyCFunction)pattern_subfn, METH_VARARGS|METH_KEYWORDS, + pattern_subfn_doc}, + {"split", (PyCFunction)pattern_split, METH_VARARGS|METH_KEYWORDS, + pattern_split_doc}, + {"splititer", (PyCFunction)pattern_splititer, METH_VARARGS|METH_KEYWORDS, + pattern_splititer_doc}, + {"findall", (PyCFunction)pattern_findall, METH_VARARGS|METH_KEYWORDS, + pattern_findall_doc}, + {"finditer", (PyCFunction)pattern_finditer, METH_VARARGS|METH_KEYWORDS, + pattern_finditer_doc}, + {"scanner", (PyCFunction)pattern_scanner, METH_VARARGS|METH_KEYWORDS, + pattern_scanner_doc}, + {"__copy__", (PyCFunction)pattern_copy, METH_NOARGS}, + {"__deepcopy__", (PyCFunction)pattern_deepcopy, METH_O}, + {"__sizeof__", (PyCFunction)pattern_sizeof, METH_NOARGS|METH_COEXIST}, +#if PY_VERSION_HEX >= 0x03090000 + {"__class_getitem__", (PyCFunction)Py_GenericAlias, METH_O|METH_CLASS, + PyDoc_STR("See PEP 585")}, +#endif + {NULL, NULL} +}; + +PyDoc_STRVAR(pattern_doc, "Compiled regex object"); + +/* Deallocates a PatternObject. */ +static void pattern_dealloc(PyObject* self_) { + PatternObject* self; + size_t i; + int partial_side; + + self = (PatternObject*)self_; + + /* Discard the nodes. */ + for (i = 0; i < self->node_count; i++) { + RE_Node* node; + + node = self->node_list[i]; + re_dealloc(node->values); + if (node->status & RE_STATUS_STRING) { + re_dealloc(node->string.bad_character_offset); + re_dealloc(node->string.good_suffix_offset); + } + re_dealloc(node); + } + re_dealloc(self->node_list); + + /* Discard the group info. */ + re_dealloc(self->group_info); + + /* Discard the call_ref info. */ + re_dealloc(self->call_ref_info); + + /* Discard the repeat info. */ + re_dealloc(self->repeat_info); + + dealloc_groups(self->groups_storage, self->true_group_count); + + dealloc_repeats(self->repeats_storage, self->repeat_count); + + re_dealloc(self->stack_storage); + + if (self->weakreflist) + PyObject_ClearWeakRefs((PyObject*)self); + Py_XDECREF(self->pattern); + Py_XDECREF(self->groupindex); + Py_XDECREF(self->indexgroup); + + for (partial_side = 0; partial_side < 2; partial_side++) { + if (self->partial_named_lists[partial_side]) { + for (i = 0; i < self->named_lists_count; i++) + Py_XDECREF(self->partial_named_lists[partial_side][i]); + + re_dealloc(self->partial_named_lists[partial_side]); + } + } + + Py_DECREF(self->named_lists); + Py_DECREF(self->named_list_indexes); + Py_DECREF(self->required_chars); + re_dealloc(self->locale_info); + Py_DECREF(self->packed_code_list); + PyObject_DEL(self); +} + +/* Info about the various flags that can be passed in. */ +typedef struct RE_FlagName { + char* name; + int value; +} RE_FlagName; + +/* We won't bother about the U flag in Python 3. */ +static RE_FlagName flag_names[] = { + {"A", RE_FLAG_ASCII}, + {"B", RE_FLAG_BESTMATCH}, + {"D", RE_FLAG_DEBUG}, + {"S", RE_FLAG_DOTALL}, + {"F", RE_FLAG_FULLCASE}, + {"I", RE_FLAG_IGNORECASE}, + {"L", RE_FLAG_LOCALE}, + {"M", RE_FLAG_MULTILINE}, + {"P", RE_FLAG_POSIX}, + {"R", RE_FLAG_REVERSE}, + {"T", RE_FLAG_TEMPLATE}, + {"X", RE_FLAG_VERBOSE}, + {"V0", RE_FLAG_VERSION0}, + {"V1", RE_FLAG_VERSION1}, + {"W", RE_FLAG_WORD}, +}; + +/* Appends a string to a list. */ +Py_LOCAL_INLINE(BOOL) append_string(PyObject* list, char* string) { + PyObject* item; + int status; + + item = Py_BuildValue("U", string); + if (!item) + return FALSE; + + status = PyList_Append(list, item); + Py_DECREF(item); + if (status < 0) + return FALSE; + + return TRUE; +} + +/* Appends a (decimal) integer to a list. */ +Py_LOCAL_INLINE(BOOL) append_integer(PyObject* list, Py_ssize_t value) { + PyObject* int_obj; + PyObject* repr_obj; + int status; + + int_obj = Py_BuildValue("n", value); + if (!int_obj) + return FALSE; + + repr_obj = PyObject_Repr(int_obj); + Py_DECREF(int_obj); + if (!repr_obj) + return FALSE; + + status = PyList_Append(list, repr_obj); + Py_DECREF(repr_obj); + if (status < 0) + return FALSE; + + return TRUE; +} + +/* Packs the code list that's needed for pickling. */ +Py_LOCAL_INLINE(PyObject*) pack_code_list(RE_CODE* code, Py_ssize_t code_len) { + Py_ssize_t max_size; + RE_UINT8* packed; + Py_ssize_t count; + RE_UINT32 value; + Py_ssize_t i; + PyObject* packed_code_list; + + /* What is the maximum number of bytes needed to store it? + * + * A 32-bit RE_CODE might need 5 bytes ((32 + 6) / 7). + */ + max_size = code_len * 5 + (Py_ssize_t)((sizeof(Py_ssize_t) * 8) + 6) / 7; + + packed = (RE_UINT8*)re_alloc((size_t)max_size); + count = 0; + + /* Store the length of the code list. */ + value = (RE_UINT32)code_len; + + while (value >= 0x80) { + packed[count++] = 0x80 | (RE_UINT8)(value & 0x7F); + value >>= 7; + } + + packed[count++] = (RE_UINT8)value; + + /* Store each of the elements of the code list. */ + for (i = 0; i < code_len; i++) { + value = (RE_UINT32)code[i]; + + while (value >= 0x80) { + packed[count++] = 0x80 | (RE_UINT8)(value & 0x7F); + value >>= 7; + } + + packed[count++] = (RE_UINT8)value; + } + + packed_code_list = PyBytes_FromStringAndSize((const char *)packed, count); + re_dealloc(packed); + + return packed_code_list; +} + +/* Unpacks the code list that's needed for pickling. */ +Py_LOCAL_INLINE(PyObject*) unpack_code_list(PyObject* packed) { + PyObject* code_list; + RE_UINT8* packed_data; + Py_ssize_t index; + RE_UINT32 value; + int shift; + size_t count; + + code_list = PyList_New(0); + if (!code_list) + return NULL; + + packed_data = (RE_UINT8*)PyBytes_AsString(packed); + index = 0; + + /* Unpack the length of the code list. */ + value = 0; + shift = 0; + + while (packed_data[index] >= 0x80) { + value |= (RE_UINT32)(packed_data[index++] & 0x7F) << shift; + shift += 7; + } + + value |= (RE_UINT32)packed_data[index++] << shift; + count = (size_t)value; + + /* Unpack each of the elements of the code list. */ + while (count > 0) { + PyObject* obj; + int status; + + value = 0; + shift = 0; + + while (packed_data[index] >= 0x80) { + value |= (RE_UINT32)(packed_data[index++] & 0x7F) << shift; + shift += 7; + } + + value |= (RE_UINT32)packed_data[index++] << shift; + obj = PyLong_FromSize_t((size_t)value); + if (!obj) + goto error; + + status = PyList_Append(code_list, obj); + Py_DECREF(obj); + if (status == -1) + goto error; + + --count; + } + + return code_list; + +error: + Py_DECREF(code_list); + return NULL; +} + +/* MatchObject's '__repr__' method. */ +static PyObject* match_repr(PyObject* self_) { + MatchObject* self; + PyObject* list; + PyObject* matched_substring; + PyObject* matched_repr; + int status; + PyObject* separator; + PyObject* result; + + self = (MatchObject*)self_; + + list = PyList_New(0); + if (!list) + return NULL; + + if (!append_string(list, "match_start)) + goto error; + + if (!append_string(list, ", ")) + goto error; + + if (!append_integer(list, self->match_end)) + goto error; + + if (!append_string(list, "), match=")) + goto error; + + matched_substring = get_slice(self->substring, self->match_start - + self->substring_offset, self->match_end - self->substring_offset); + if (!matched_substring) + goto error; + + matched_repr = PyObject_Repr(matched_substring); + Py_DECREF(matched_substring); + if (!matched_repr) + goto error; + + status = PyList_Append(list, matched_repr); + Py_DECREF(matched_repr); + if (status < 0) + goto error; + + if (self->fuzzy_counts[RE_FUZZY_SUB] != 0 || + self->fuzzy_counts[RE_FUZZY_INS] != 0 || self->fuzzy_counts[RE_FUZZY_DEL] + != 0) { + if (!append_string(list, ", fuzzy_counts=(")) + goto error; + + if (!append_integer(list, + (Py_ssize_t)self->fuzzy_counts[RE_FUZZY_SUB])) + goto error; + + if (!append_string(list, ", ")) + goto error; + + if (!append_integer(list, + (Py_ssize_t)self->fuzzy_counts[RE_FUZZY_INS])) + goto error; + + if (!append_string(list, ", ")) + goto error; + if (!append_integer(list, + (Py_ssize_t)self->fuzzy_counts[RE_FUZZY_DEL])) + goto error; + + if (!append_string(list, ")")) + goto error; + } + + if (self->partial) { + if (!append_string(list, ", partial=True")) + goto error; + } + + if (!append_string(list, ">")) + goto error; + + separator = Py_BuildValue("U", ""); + if (!separator) + goto error; + + result = PyUnicode_Join(separator, list); + Py_DECREF(separator); + Py_DECREF(list); + + return result; + +error: + Py_DECREF(list); + return NULL; +} + +/* PatternObject's '__repr__' method. */ +static PyObject* pattern_repr(PyObject* self_) { + PatternObject* self; + PyObject* list; + PyObject* item; + int status; + int flag_count; + unsigned int i; + Py_ssize_t pos; + PyObject* key; + PyObject* value; + PyObject* separator; + PyObject* result; + + self = (PatternObject*)self_; + + list = PyList_New(0); + if (!list) + return NULL; + + if (!append_string(list, "regex.Regex(")) + goto error; + + item = PyObject_Repr(self->pattern); + if (!item) + goto error; + + status = PyList_Append(list, item); + Py_DECREF(item); + if (status < 0) + goto error; + + flag_count = 0; + for (i = 0; i < sizeof(flag_names) / sizeof(flag_names[0]); i++) { + if (self->flags & flag_names[i].value) { + if (flag_count == 0) { + if (!append_string(list, ", flags=")) + goto error; + } else { + if (!append_string(list, " | ")) + goto error; + } + + if (!append_string(list, "regex.")) + goto error; + + if (!append_string(list, flag_names[i].name)) + goto error; + + ++flag_count; + } + } + + pos = 0; + /* PyDict_Next borrows references. */ + while (PyDict_Next(self->named_lists, &pos, &key, &value)) { + if (!append_string(list, ", ")) + goto error; + + status = PyList_Append(list, key); + if (status < 0) + goto error; + + if (!append_string(list, "=")) + goto error; + + item = PyObject_Repr(value); + if (!item) + goto error; + + status = PyList_Append(list, item); + Py_DECREF(item); + if (status < 0) + goto error; + } + + if (!append_string(list, ")")) + goto error; + + separator = Py_BuildValue("U", ""); + if (!separator) + goto error; + + result = PyUnicode_Join(separator, list); + Py_DECREF(separator); + Py_DECREF(list); + + return result; + +error: + Py_DECREF(list); + return NULL; +} + +/* PatternObject's 'groupindex' method. */ +static PyObject* pattern_groupindex(PyObject* self_) { + PatternObject* self; + + self = (PatternObject*)self_; + + return PyDict_Copy(self->groupindex); +} + +/* PatternObject's '_pickled_data' method. */ +static PyObject* pattern_pickled_data(PyObject* self_) { + PatternObject* self; + PyObject* pickled_data; + + self = (PatternObject*)self_; + + /* Build the data needed for picking. */ + pickled_data = Py_BuildValue("OnOOOOOnOnn", self->pattern, self->flags, + self->packed_code_list, self->groupindex, self->indexgroup, + self->named_lists, self->named_list_indexes, self->req_offset, + self->required_chars, self->req_flags, self->public_group_count); + + return pickled_data; +} + +static PyGetSetDef pattern_getset[] = { + {"groupindex", (getter)pattern_groupindex, (setter)NULL, + "A dictionary mapping group names to group numbers."}, + {"_pickled_data", (getter)pattern_pickled_data, (setter)NULL, + "Data used for pickling."}, + {NULL} /* Sentinel */ +}; + +static PyMemberDef pattern_members[] = { + {"pattern", T_OBJECT, offsetof(PatternObject, pattern), READONLY, + "The pattern string from which the regex object was compiled."}, + {"flags", T_PYSSIZET, offsetof(PatternObject, flags), READONLY, + "The regex matching flags."}, + {"groups", T_PYSSIZET, offsetof(PatternObject, public_group_count), + READONLY, "The number of capturing groups in the pattern."}, + {"named_lists", T_OBJECT, offsetof(PatternObject, named_lists), READONLY, + "The named lists used by the regex."}, + {NULL} /* Sentinel */ +}; + +static PyTypeObject Pattern_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "_regex.Pattern", + sizeof(PatternObject) +}; + +/* Building the nodes is made simpler by allowing branches to have a single + * exit. These need to be removed. + */ +Py_LOCAL_INLINE(void) skip_one_way_branches(PatternObject* pattern) { + BOOL modified; + + /* If a node refers to a 1-way branch then make the former refer to the + * latter's destination. Repeat until they're all done. + */ + do { + size_t i; + + modified = FALSE; + + for (i = 0; i < pattern->node_count; i++) { + RE_Node* node; + RE_Node* next; + + node = pattern->node_list[i]; + + /* Check the first destination. */ + next = node->next_1.node; + if (next && next->op == RE_OP_BRANCH && + !next->nonstring.next_2.node) { + node->next_1.node = next->next_1.node; + modified = TRUE; + } + + /* Check the second destination. */ + next = node->nonstring.next_2.node; + if (next && next->op == RE_OP_BRANCH && + !next->nonstring.next_2.node) { + node->nonstring.next_2.node = next->next_1.node; + modified = TRUE; + } + + /* Check the true branch for CONDITIONAL. */ + next = node->nonstring.true_node; + if (next && next->op == RE_OP_BRANCH && + !next->nonstring.true_node) { + node->nonstring.true_node = next->next_1.node; + modified = TRUE; + } + } + } while (modified); + + /* The start node might be a 1-way branch. Skip over it because it'll be + * removed. It might even be the first in a chain. + */ + while (pattern->start_node->op == RE_OP_BRANCH && + !pattern->start_node->nonstring.next_2.node) + pattern->start_node = pattern->start_node->next_1.node; +} + +/* Initialises a check stack. */ +Py_LOCAL_INLINE(void) CheckStack_init(RE_CheckStack* stack) { + stack->capacity = 0; + stack->count = 0; + stack->items = NULL; +} + +/* Finalises a check stack. */ +Py_LOCAL_INLINE(void) CheckStack_fini(RE_CheckStack* stack) { + PyMem_Free(stack->items); + stack->capacity = 0; + stack->count = 0; + stack->items = NULL; +} + +/* Pushes an item onto a check stack. */ +Py_LOCAL_INLINE(BOOL) CheckStack_push(RE_CheckStack* stack, RE_Node* node, + RE_STATUS_T result) { + RE_Check* check; + + if (stack->count >= stack->capacity) { + size_t new_capacity; + RE_Check* new_items; + + new_capacity = stack->capacity * 2; + if (new_capacity == 0) + new_capacity = 16; + + new_items = (RE_Check*)PyMem_Realloc(stack->items, new_capacity * + sizeof(RE_Check)); + if (!new_items) + return FALSE; + + stack->capacity = new_capacity; + stack->items = new_items; + } + + check = &stack->items[stack->count++]; + check->node = node; + check->result = result; + + return TRUE; +} + +/* Pops an item off a check stack. Returns NULL if the stack is empty. */ +Py_LOCAL_INLINE(RE_Check*) CheckStack_pop(RE_CheckStack* stack) { + return stack->count > 0 ? &stack->items[--stack->count] : NULL; +} + +/* Adds guards to repeats which are followed by a reference to a group. */ +Py_LOCAL_INLINE(RE_STATUS_T) add_repeat_guards(PatternObject* pattern, RE_Node* + start_node) { + RE_CheckStack stack; + + CheckStack_init(&stack); + + CheckStack_push(&stack, start_node, RE_STATUS_NEITHER); + + for (;;) { + RE_Check* check; + RE_Node* node; + RE_STATUS_T result; + + check = CheckStack_pop(&stack); + + if (!check) + break; + + node = check->node; + result = check->result; + + if (!(node->status & RE_STATUS_VISITED_AG)) { + switch (check->node->op) { + case RE_OP_BRANCH: + { + RE_Node* branch_1; + RE_Node* branch_2; + BOOL visited_branch_1; + BOOL visited_branch_2; + + branch_1 = node->next_1.node; + branch_2 = node->nonstring.next_2.node; + visited_branch_1 = (branch_1->status & RE_STATUS_VISITED_AG); + visited_branch_2 = (branch_2->status & RE_STATUS_VISITED_AG); + + if (visited_branch_1 && visited_branch_2) { + RE_STATUS_T branch_1_result; + RE_STATUS_T branch_2_result; + + branch_1_result = branch_1->status & (RE_STATUS_REPEAT | + RE_STATUS_REF); + branch_2_result = branch_2->status & (RE_STATUS_REPEAT | + RE_STATUS_REF); + + node->status |= RE_STATUS_VISITED_AG | max_status_3(result, + branch_1_result, branch_2_result); + } else { + CheckStack_push(&stack, node, result); + if (!visited_branch_2) + CheckStack_push(&stack, branch_2, RE_STATUS_NEITHER); + if (!visited_branch_1) + CheckStack_push(&stack, branch_1, RE_STATUS_NEITHER); + } + break; + } + case RE_OP_END_GREEDY_REPEAT: + case RE_OP_END_LAZY_REPEAT: + node->status |= RE_STATUS_VISITED_AG; + break; + case RE_OP_GREEDY_REPEAT: + case RE_OP_LAZY_REPEAT: + { + BOOL limited; + RE_Node* body; + RE_Node* tail; + BOOL visited_body; + BOOL visited_tail; + + limited = ~node->values[2] != 0; + + body = node->next_1.node; + tail = node->nonstring.next_2.node; + visited_body = (body->status & RE_STATUS_VISITED_AG); + visited_tail = (tail->status & RE_STATUS_VISITED_AG); + + if (visited_body && visited_tail) { + RE_STATUS_T body_result; + RE_STATUS_T tail_result; + RE_RepeatInfo* repeat_info; + + body_result = body->status & (RE_STATUS_REPEAT | + RE_STATUS_REF); + tail_result = tail->status & (RE_STATUS_REPEAT | + RE_STATUS_REF); + + repeat_info = &pattern->repeat_info[node->values[0]]; + if (body_result != RE_STATUS_REF) + repeat_info->status |= RE_STATUS_BODY; + if (tail_result != RE_STATUS_REF) + repeat_info->status |= RE_STATUS_TAIL; + + if (limited) + result = max_status_2(result, RE_STATUS_LIMITED); + else + result = max_status_2(result, RE_STATUS_REPEAT); + node->status |= RE_STATUS_VISITED_AG | max_status_3(result, + body_result, tail_result); + } else { + CheckStack_push(&stack, node, result); + if (!visited_tail) + CheckStack_push(&stack, tail, RE_STATUS_NEITHER); + if (!visited_body) { + if (limited) + body->status |= RE_STATUS_VISITED_AG | + RE_STATUS_LIMITED; + else + CheckStack_push(&stack, body, RE_STATUS_NEITHER); + } + } + break; + } + case RE_OP_GREEDY_REPEAT_ONE: + case RE_OP_LAZY_REPEAT_ONE: + { + RE_Node* tail; + BOOL visited_tail; + + tail = node->next_1.node; + visited_tail = (tail->status & RE_STATUS_VISITED_AG); + + if (visited_tail) { + BOOL limited; + RE_STATUS_T tail_result; + RE_RepeatInfo* repeat_info; + + limited = ~node->values[2] != 0; + + tail_result = tail->status & (RE_STATUS_REPEAT | + RE_STATUS_REF); + + repeat_info = &pattern->repeat_info[node->values[0]]; + /* Removing guard here to fix issue 494 and prevent + * regression of issue 495. + */ + /* repeat_info->status |= RE_STATUS_BODY; */ + + if (tail_result != RE_STATUS_REF) + repeat_info->status |= RE_STATUS_TAIL; + + if (limited) + result = max_status_2(result, RE_STATUS_LIMITED); + else + result = max_status_2(result, RE_STATUS_REPEAT); + node->status |= RE_STATUS_VISITED_AG | max_status_3(result, + RE_STATUS_REPEAT, tail_result); + } else { + CheckStack_push(&stack, node, result); + CheckStack_push(&stack, tail, RE_STATUS_NEITHER); + } + break; + } + case RE_OP_GROUP_EXISTS: + { + RE_Node* branch_1; + RE_Node* branch_2; + BOOL visited_branch_1; + BOOL visited_branch_2; + + branch_1 = node->next_1.node; + branch_2 = node->nonstring.next_2.node; + visited_branch_1 = (branch_1->status & RE_STATUS_VISITED_AG); + visited_branch_2 = (branch_2->status & RE_STATUS_VISITED_AG); + + if (visited_branch_1 && visited_branch_2) { + RE_STATUS_T branch_1_result; + RE_STATUS_T branch_2_result; + + branch_1_result = branch_1->status & (RE_STATUS_REPEAT | + RE_STATUS_REF); + branch_2_result = branch_2->status & (RE_STATUS_REPEAT | + RE_STATUS_REF); + + node->status |= RE_STATUS_VISITED_AG | max_status_4(result, + branch_1_result, branch_2_result, RE_STATUS_REF); + } else { + CheckStack_push(&stack, node, result); + if (!visited_branch_2) + CheckStack_push(&stack, branch_2, RE_STATUS_NEITHER); + if (!visited_branch_1) + CheckStack_push(&stack, branch_1, RE_STATUS_NEITHER); + } + break; + } + case RE_OP_REF_GROUP: + case RE_OP_REF_GROUP_FLD: + case RE_OP_REF_GROUP_FLD_REV: + case RE_OP_REF_GROUP_IGN: + case RE_OP_REF_GROUP_IGN_REV: + case RE_OP_REF_GROUP_REV: + { + RE_Node* tail; + BOOL visited_tail; + + tail = node->next_1.node; + visited_tail = (tail->status & RE_STATUS_VISITED_AG); + + if (visited_tail) + node->status |= RE_STATUS_VISITED_AG | RE_STATUS_REF; + else { + CheckStack_push(&stack, node, result); + CheckStack_push(&stack, tail, RE_STATUS_NEITHER); + } + break; + } + case RE_OP_SUCCESS: + node->status |= RE_STATUS_VISITED_AG | result; + break; + default: + { + RE_Node* tail; + BOOL visited_tail; + RE_STATUS_T tail_result; + + tail = node->next_1.node; + + if (!tail) { + node->status |= RE_STATUS_VISITED_AG | result; + break; + } + + visited_tail = (tail->status & RE_STATUS_VISITED_AG); + + if (visited_tail) { + tail_result = tail->status & (RE_STATUS_REPEAT | + RE_STATUS_REF); + node->status |= RE_STATUS_VISITED_AG | tail_result; + } else { + CheckStack_push(&stack, node, result); + CheckStack_push(&stack, node->next_1.node, result); + } + break; + } + } + } + } + + CheckStack_fini(&stack); + + return start_node->status & (RE_STATUS_REPEAT | RE_STATUS_REF); +} + +/* Adds an index to a node's values unless it's already present. + * + * 'offset' is the offset of the index count within the values. + */ +Py_LOCAL_INLINE(BOOL) add_index(RE_Node* node, size_t offset, size_t index) { + size_t index_count; + size_t first_index; + size_t i; + RE_CODE* new_values; + + if (!node) + return TRUE; + + index_count = node->values[offset]; + first_index = offset + 1; + + /* Is the index already present? */ + for (i = 0; i < index_count; i++) { + if (node->values[first_index + i] == index) + return TRUE; + } + + /* Allocate more space for the new index. */ + new_values = re_realloc(node->values, (node->value_count + 1) * + sizeof(RE_CODE)); + if (!new_values) + return FALSE; + + ++node->value_count; + node->values = new_values; + + node->values[first_index + node->values[offset]++] = (RE_CODE)index; + + return TRUE; +} + +/* Records the index of every repeat and fuzzy section within atomic + * subpatterns and lookarounds. + */ +Py_LOCAL_INLINE(BOOL) record_subpattern_repeats_and_fuzzy_sections(RE_Node* + parent_node, size_t offset, size_t repeat_count, RE_Node* node) { + while (node) { + if (node->status & RE_STATUS_VISITED_REP) + return TRUE; + + node->status |= RE_STATUS_VISITED_REP; + + switch (node->op) { + case RE_OP_BRANCH: + case RE_OP_GROUP_EXISTS: + if (!record_subpattern_repeats_and_fuzzy_sections(parent_node, + offset, repeat_count, node->next_1.node)) + return FALSE; + node = node->nonstring.next_2.node; + break; + case RE_OP_END_FUZZY: + node = node->next_1.node; + break; + case RE_OP_END_GREEDY_REPEAT: + case RE_OP_END_LAZY_REPEAT: + return TRUE; + case RE_OP_FUZZY: + /* Record the fuzzy index. */ + if (!add_index(parent_node, offset, repeat_count + + node->values[0])) + return FALSE; + node = node->next_1.node; + break; + case RE_OP_GREEDY_REPEAT: + case RE_OP_LAZY_REPEAT: + /* Record the repeat index. */ + if (!add_index(parent_node, offset, node->values[0])) + return FALSE; + if (!record_subpattern_repeats_and_fuzzy_sections(parent_node, + offset, repeat_count, node->next_1.node)) + return FALSE; + node = node->nonstring.next_2.node; + break; + case RE_OP_GREEDY_REPEAT_ONE: + case RE_OP_LAZY_REPEAT_ONE: + /* Record the repeat index. */ + if (!add_index(parent_node, offset, node->values[0])) + return FALSE; + node = node->next_1.node; + break; + default: + node = node->next_1.node; + break; + } + } + + return TRUE; +} + +/* Initialises a node stack. */ +Py_LOCAL_INLINE(void) NodeStack_init(RE_NodeStack* stack) { + stack->capacity = 0; + stack->count = 0; + stack->items = NULL; +} + +/* Finalises a node stack. */ +Py_LOCAL_INLINE(void) NodeStack_fini(RE_NodeStack* stack) { + PyMem_Free(stack->items); + stack->capacity = 0; + stack->count = 0; + stack->items = NULL; +} + +/* Pushes an item onto a node stack. */ +Py_LOCAL_INLINE(BOOL) NodeStack_push(RE_NodeStack* stack, RE_Node* node) { + if (stack->count >= stack->capacity) { + size_t new_capacity; + RE_Node** new_items; + + new_capacity = stack->capacity * 2; + if (new_capacity == 0) + new_capacity = 16; + + new_items = (RE_Node**)PyMem_Realloc(stack->items, new_capacity * + sizeof(RE_Node*)); + if (!new_items) + return FALSE; + + stack->capacity = new_capacity; + stack->items = new_items; + } + + stack->items[stack->count++] = node; + + return TRUE; +} + +/* Pops an item off a node stack. Returns NULL if the stack is empty. */ +Py_LOCAL_INLINE(RE_Node*) NodeStack_pop(RE_NodeStack* stack) { + return stack->count > 0 ? stack->items[--stack->count] : NULL; +} + +/* Marks nodes which are being used as used. */ +Py_LOCAL_INLINE(void) use_nodes(RE_Node* node) { + RE_NodeStack stack; + + NodeStack_init(&stack); + + while (node) { + while (node && !(node->status & RE_STATUS_USED)) { + node->status |= RE_STATUS_USED; + if (!(node->status & RE_STATUS_STRING)) { + if (node->nonstring.next_2.node) + NodeStack_push(&stack, node->nonstring.next_2.node); + } + node = node->next_1.node; + } + node = NodeStack_pop(&stack); + } + + NodeStack_fini(&stack); +} + +/* Discards any unused nodes. + * + * Optimising the nodes might result in some nodes no longer being used. + */ +Py_LOCAL_INLINE(void) discard_unused_nodes(PatternObject* pattern) { + size_t i; + size_t new_count; + + /* Mark the nodes which are being used. */ + use_nodes(pattern->start_node); + + for (i = 0; i < pattern->call_ref_info_capacity; i++) + use_nodes(pattern->call_ref_info[i].node); + + new_count = 0; + for (i = 0; i < pattern->node_count; i++) { + RE_Node* node; + + node = pattern->node_list[i]; + if (node->status & RE_STATUS_USED) + pattern->node_list[new_count++] = node; + else { + re_dealloc(node->values); + if (node->status & RE_STATUS_STRING) { + re_dealloc(node->string.bad_character_offset); + re_dealloc(node->string.good_suffix_offset); + } + re_dealloc(node); + } + } + + pattern->node_count = new_count; +} + +/* Marks all the group which are named. Returns FALSE if there's an error. */ +Py_LOCAL_INLINE(BOOL) mark_named_groups(PatternObject* pattern) { + size_t i; + + for (i = 0; i < pattern->public_group_count; i++) { + RE_GroupInfo* group_info; + PyObject* index; + int status; + + group_info = &pattern->group_info[i]; + index = Py_BuildValue("n", i + 1); + if (!index) + return FALSE; + + status = PyDict_Contains(pattern->indexgroup, index); + Py_DECREF(index); + if (status < 0) + return FALSE; + + group_info->has_name = status == 1; + } + + return TRUE; +} + +/* Checks whether you can look ahead of this node for testing for a match. */ +Py_LOCAL_INLINE(BOOL) can_test_past(RE_Node* node) { + switch (node->op) { + case RE_OP_END_GROUP: + case RE_OP_START_GROUP: + return TRUE; + case RE_OP_GREEDY_REPEAT: + case RE_OP_LAZY_REPEAT: + return node->values[1] > 0; + default: + return FALSE; + } +} + +/* Gets the test node. + * + * The test node lets the matcher look ahead in the pattern, allowing it to + * avoid the cost of housekeeping, only to find that what follows doesn't match + * anyway. + */ +Py_LOCAL_INLINE(void) set_test_node(RE_NextNode* next) { + RE_Node* node = next->node; + RE_Node* test; + + next->test = node; + next->match_next = node; + next->match_step = 0; + + if (!node) + return; + + test = node; + while (can_test_past(test)) + test = test->next_1.node; + + next->test = test; + + if (test != node) + return; + + switch (test->op) { + case RE_OP_ANY: + case RE_OP_ANY_ALL: + case RE_OP_ANY_ALL_REV: + case RE_OP_ANY_REV: + case RE_OP_ANY_U: + case RE_OP_ANY_U_REV: + case RE_OP_BOUNDARY: + case RE_OP_CHARACTER: + case RE_OP_CHARACTER_IGN: + case RE_OP_CHARACTER_IGN_REV: + case RE_OP_CHARACTER_REV: + case RE_OP_DEFAULT_BOUNDARY: + case RE_OP_DEFAULT_END_OF_WORD: + case RE_OP_DEFAULT_START_OF_WORD: + case RE_OP_END_OF_LINE: + case RE_OP_END_OF_LINE_U: + case RE_OP_END_OF_STRING: + case RE_OP_END_OF_STRING_LINE: + case RE_OP_END_OF_STRING_LINE_U: + case RE_OP_END_OF_WORD: + case RE_OP_GRAPHEME_BOUNDARY: + case RE_OP_PROPERTY: + case RE_OP_PROPERTY_IGN: + case RE_OP_PROPERTY_IGN_REV: + case RE_OP_PROPERTY_REV: + case RE_OP_RANGE: + case RE_OP_RANGE_IGN: + case RE_OP_RANGE_IGN_REV: + case RE_OP_RANGE_REV: + case RE_OP_SEARCH_ANCHOR: + case RE_OP_SET_DIFF: + case RE_OP_SET_DIFF_IGN: + case RE_OP_SET_DIFF_IGN_REV: + case RE_OP_SET_DIFF_REV: + case RE_OP_SET_INTER: + case RE_OP_SET_INTER_IGN: + case RE_OP_SET_INTER_IGN_REV: + case RE_OP_SET_INTER_REV: + case RE_OP_SET_SYM_DIFF: + case RE_OP_SET_SYM_DIFF_IGN: + case RE_OP_SET_SYM_DIFF_IGN_REV: + case RE_OP_SET_SYM_DIFF_REV: + case RE_OP_SET_UNION: + case RE_OP_SET_UNION_IGN: + case RE_OP_SET_UNION_IGN_REV: + case RE_OP_SET_UNION_REV: + case RE_OP_START_OF_LINE: + case RE_OP_START_OF_LINE_U: + case RE_OP_START_OF_STRING: + case RE_OP_START_OF_WORD: + case RE_OP_STRING: + case RE_OP_STRING_FLD: + case RE_OP_STRING_FLD_REV: + case RE_OP_STRING_IGN: + case RE_OP_STRING_IGN_REV: + case RE_OP_STRING_REV: + next->match_next = test->next_1.node; + next->match_step = test->step; + break; + case RE_OP_GREEDY_REPEAT_ONE: + case RE_OP_LAZY_REPEAT_ONE: + if (test->values[1] > 0) + next->test = test; + break; + } +} + +/* Sets the test nodes. */ +Py_LOCAL_INLINE(void) set_test_nodes(PatternObject* pattern) { + RE_Node** node_list; + size_t i; + + node_list = pattern->node_list; + for (i = 0; i < pattern->node_count; i++) { + RE_Node* node; + + node = node_list[i]; + set_test_node(&node->next_1); + if (!(node->status & RE_STATUS_STRING)) + set_test_node(&node->nonstring.next_2); + } +} + +/* Optimises the pattern. */ +Py_LOCAL_INLINE(BOOL) optimise_pattern(PatternObject* pattern) { + size_t i; + + /* Building the nodes is made simpler by allowing branches to have a single + * exit. These need to be removed. + */ + skip_one_way_branches(pattern); + + /* Add position guards for repeat bodies containing a reference to a group + * or repeat tails followed at some point by a reference to a group. + */ + add_repeat_guards(pattern, pattern->start_node); + + /* Record the index of repeats and fuzzy sections within the body of atomic + * and lookaround nodes. + */ + if (!record_subpattern_repeats_and_fuzzy_sections(NULL, 0, + pattern->repeat_count, pattern->start_node)) + return FALSE; + + for (i = 0; i < pattern->call_ref_info_count; i++) { + RE_Node* node; + + node = pattern->call_ref_info[i].node; + if (!record_subpattern_repeats_and_fuzzy_sections(NULL, 0, + pattern->repeat_count, node)) + return FALSE; + } + + /* Discard any unused nodes. */ + discard_unused_nodes(pattern); + + /* Set the test nodes. */ + set_test_nodes(pattern); + + /* Mark all the group that are named. */ + if (!mark_named_groups(pattern)) + return FALSE; + + return TRUE; +} + +/* Creates a new pattern node. */ +Py_LOCAL_INLINE(RE_Node*) create_node(PatternObject* pattern, RE_UINT8 op, + RE_CODE flags, Py_ssize_t step, size_t value_count) { + RE_Node* node; + + node = (RE_Node*)re_alloc(sizeof(*node)); + if (!node) + return NULL; + memset(node, 0, sizeof(RE_Node)); + + node->value_count = value_count; + + if (node->value_count > 0) { + node->values = (RE_CODE*)re_alloc(node->value_count * sizeof(RE_CODE)); + if (!node->values) + goto error; + } else + node->values = NULL; + + node->op = op; + node->match = (flags & RE_POSITIVE_OP) != 0; + node->status = (RE_STATUS_T)(flags << RE_STATUS_SHIFT); + node->step = step; + + /* Ensure that there's enough storage to record the new node. */ + if (pattern->node_count >= pattern->node_capacity) { + size_t new_capacity; + RE_Node** new_node_list; + + new_capacity = pattern->node_capacity * 2; + + if (new_capacity == 0) + new_capacity = 16; + + new_node_list = (RE_Node**)re_realloc(pattern->node_list, new_capacity + * sizeof(RE_Node*)); + if (!new_node_list) + goto error; + + pattern->node_list = new_node_list; + pattern->node_capacity = new_capacity; + } + + /* Record the new node. */ + pattern->node_list[pattern->node_count++] = node; + + return node; + +error: + re_dealloc(node->values); + re_dealloc(node); + return NULL; +} + +/* Adds a node as a next node for another node. */ +Py_LOCAL_INLINE(void) add_node(RE_Node* node_1, RE_Node* node_2) { + if (!node_1->next_1.node) + node_1->next_1.node = node_2; + else + node_1->nonstring.next_2.node = node_2; +} + +/* Ensures that the entry for a group's details actually exists. */ +Py_LOCAL_INLINE(BOOL) ensure_group(PatternObject* pattern, size_t group) { + size_t old_capacity; + size_t new_capacity; + RE_GroupInfo* new_group_info; + + if (group <= pattern->true_group_count) + /* We already have an entry for the group. */ + return TRUE; + + /* Increase the storage capacity to include the new entry if it's + * insufficient. + */ + old_capacity = pattern->group_info_capacity; + new_capacity = pattern->group_info_capacity; + + while (group > new_capacity) + new_capacity += 16; + + if (new_capacity > old_capacity) { + new_group_info = (RE_GroupInfo*)re_realloc(pattern->group_info, + new_capacity * sizeof(RE_GroupInfo)); + if (!new_group_info) + return FALSE; + + memset(new_group_info + old_capacity, 0, (new_capacity - old_capacity) + * sizeof(RE_GroupInfo)); + + pattern->group_info = new_group_info; + pattern->group_info_capacity = new_capacity; + } + + pattern->true_group_count = group; + + return TRUE; +} + +/* Records that there's a reference to a group. */ +Py_LOCAL_INLINE(BOOL) record_ref_group(PatternObject* pattern, size_t group) { + if (!ensure_group(pattern, group)) + return FALSE; + + pattern->group_info[group - 1].referenced = TRUE; + + return TRUE; +} + +/* Records that there's a new group. */ +Py_LOCAL_INLINE(BOOL) record_group(PatternObject* pattern, size_t group, + RE_Node* node) { + if (!ensure_group(pattern, group)) + return FALSE; + + if (group >= 1) { + RE_GroupInfo* info; + + info = &pattern->group_info[group - 1]; + info->end_index = (Py_ssize_t)pattern->true_group_count; + info->node = node; + } + + return TRUE; +} + +/* Records that a group has closed. */ +Py_LOCAL_INLINE(void) record_group_end(PatternObject* pattern, size_t group) { + if (group >= 1) + pattern->group_info[group - 1].end_index = ++pattern->group_end_index; +} + +/* Ensures that the entry for a call_ref's details actually exists. */ +Py_LOCAL_INLINE(BOOL) ensure_call_ref(PatternObject* pattern, size_t call_ref) + { + size_t old_capacity; + size_t new_capacity; + RE_CallRefInfo* new_call_ref_info; + + if (call_ref < pattern->call_ref_info_count) + /* We already have an entry for the call_ref. */ + return TRUE; + + /* Increase the storage capacity to include the new entry if it's + * insufficient. + */ + old_capacity = pattern->call_ref_info_capacity; + new_capacity = pattern->call_ref_info_capacity; + while (call_ref >= new_capacity) + new_capacity += 16; + + if (new_capacity > old_capacity) { + new_call_ref_info = (RE_CallRefInfo*)re_realloc(pattern->call_ref_info, + new_capacity * sizeof(RE_CallRefInfo)); + if (!new_call_ref_info) + return FALSE; + + memset(new_call_ref_info + old_capacity, 0, (new_capacity - + old_capacity) * sizeof(RE_CallRefInfo)); + + pattern->call_ref_info = new_call_ref_info; + pattern->call_ref_info_capacity = new_capacity; + } + + pattern->call_ref_info_count = 1 + call_ref; + + return TRUE; +} + +/* Records that a call_ref is defined. */ +Py_LOCAL_INLINE(BOOL) record_call_ref_defined(PatternObject* pattern, size_t + call_ref, RE_Node* node) { + if (!ensure_call_ref(pattern, call_ref)) + return FALSE; + + pattern->call_ref_info[call_ref].defined = TRUE; + pattern->call_ref_info[call_ref].node = node; + + return TRUE; +} + +/* Records that a call_ref is used. */ +Py_LOCAL_INLINE(BOOL) record_call_ref_used(PatternObject* pattern, size_t + call_ref) { + if (!ensure_call_ref(pattern, call_ref)) + return FALSE; + + pattern->call_ref_info[call_ref].used = TRUE; + + return TRUE; +} + +/* Checks whether a node matches one and only one character. */ +Py_LOCAL_INLINE(BOOL) sequence_matches_one(RE_Node* node) { + while (node->op == RE_OP_BRANCH && !node->nonstring.next_2.node) + node = node->next_1.node; + + if (node->next_1.node || (node->status & RE_STATUS_FUZZY)) + return FALSE; + + return node_matches_one_character(node); +} + +/* Records a repeat. */ +Py_LOCAL_INLINE(BOOL) record_repeat(PatternObject* pattern, size_t index, + size_t repeat_depth) { + size_t old_capacity; + size_t new_capacity; + + /* Increase the storage capacity to include the new entry if it's + * insufficient. + */ + old_capacity = pattern->repeat_info_capacity; + new_capacity = pattern->repeat_info_capacity; + while (index >= new_capacity) + new_capacity += 16; + + if (new_capacity > old_capacity) { + RE_RepeatInfo* new_repeat_info; + + new_repeat_info = (RE_RepeatInfo*)re_realloc(pattern->repeat_info, + new_capacity * sizeof(RE_RepeatInfo)); + if (!new_repeat_info) + return FALSE; + + memset(new_repeat_info + old_capacity, 0, (new_capacity - old_capacity) + * sizeof(RE_RepeatInfo)); + + pattern->repeat_info = new_repeat_info; + pattern->repeat_info_capacity = new_capacity; + } + + if (index >= pattern->repeat_count) + pattern->repeat_count = index + 1; + + if (repeat_depth > 0) + pattern->repeat_info[index].status |= RE_STATUS_INNER; + + return TRUE; +} + +Py_LOCAL_INLINE(Py_ssize_t) get_step(RE_CODE op) { + switch (op) { + case RE_OP_ANY: + case RE_OP_ANY_ALL: + case RE_OP_ANY_U: + case RE_OP_CHARACTER: + case RE_OP_CHARACTER_IGN: + case RE_OP_PROPERTY: + case RE_OP_PROPERTY_IGN: + case RE_OP_RANGE: + case RE_OP_RANGE_IGN: + case RE_OP_SET_DIFF: + case RE_OP_SET_DIFF_IGN: + case RE_OP_SET_INTER: + case RE_OP_SET_INTER_IGN: + case RE_OP_SET_SYM_DIFF: + case RE_OP_SET_SYM_DIFF_IGN: + case RE_OP_SET_UNION: + case RE_OP_SET_UNION_IGN: + case RE_OP_STRING: + case RE_OP_STRING_FLD: + case RE_OP_STRING_IGN: + return 1; + case RE_OP_ANY_ALL_REV: + case RE_OP_ANY_REV: + case RE_OP_ANY_U_REV: + case RE_OP_CHARACTER_IGN_REV: + case RE_OP_CHARACTER_REV: + case RE_OP_PROPERTY_IGN_REV: + case RE_OP_PROPERTY_REV: + case RE_OP_RANGE_IGN_REV: + case RE_OP_RANGE_REV: + case RE_OP_SET_DIFF_IGN_REV: + case RE_OP_SET_DIFF_REV: + case RE_OP_SET_INTER_IGN_REV: + case RE_OP_SET_INTER_REV: + case RE_OP_SET_SYM_DIFF_IGN_REV: + case RE_OP_SET_SYM_DIFF_REV: + case RE_OP_SET_UNION_IGN_REV: + case RE_OP_SET_UNION_REV: + case RE_OP_STRING_FLD_REV: + case RE_OP_STRING_IGN_REV: + case RE_OP_STRING_REV: + return -1; + } + + return 0; +} + +Py_LOCAL_INLINE(int) build_charset_equiv(RE_CompileArgs* args); +Py_LOCAL_INLINE(int) build_sequence(RE_CompileArgs* args); + +/* Builds an ANY node. */ +Py_LOCAL_INLINE(int) build_ANY(RE_CompileArgs* args) { + RE_UINT8 op; + RE_CODE flags; + Py_ssize_t step; + RE_Node* node; + + /* codes: opcode, flags. */ + if (args->code + 1 > args->end_code) + return RE_ERROR_ILLEGAL; + + op = (RE_UINT8)args->code[0]; + flags = args->code[1]; + + step = get_step(op); + + /* Create the node. */ + node = create_node(args->pattern, op, flags, step, 0); + if (!node) + return RE_ERROR_MEMORY; + + args->code += 2; + + /* Append the node. */ + add_node(args->end, node); + args->end = node; + + ++args->min_width; + + return RE_ERROR_SUCCESS; +} + +/* Builds a FUZZY node. */ +Py_LOCAL_INLINE(int) build_FUZZY(RE_CompileArgs* args) { + BOOL is_ext; + RE_CODE flags; + RE_Node* start_node; + RE_Node* end_node; + RE_CODE index; + RE_CompileArgs subargs; + RE_Node* test_node; + int status; + + /* codes: FUZZY, flags, constraints, ..., end + * or: FUZZY_EXT, flags, + * constraints, ... next ..., end. + */ + is_ext = args->code[0] == RE_OP_FUZZY_EXT; + if (args->code + (is_ext ? 15 : 13) > args->end_code) + return RE_ERROR_ILLEGAL; + + flags = args->code[1]; + + /* Create nodes for the start and end of the fuzzy sequence. */ + start_node = create_node(args->pattern, RE_OP_FUZZY, flags, 0, 13); + end_node = create_node(args->pattern, RE_OP_END_FUZZY, flags, 0, 0); + if (!start_node || !end_node) + return RE_ERROR_MEMORY; + + index = (RE_CODE)args->pattern->fuzzy_count++; + start_node->values[0] = index; + + /* The constraints consist of 4 pairs of limits and the cost equation. */ + start_node->values[RE_FUZZY_VAL_MIN_DEL] = args->code[2]; /* Deletion minimum. */ + start_node->values[RE_FUZZY_VAL_MIN_INS] = args->code[4]; /* Insertion minimum. */ + start_node->values[RE_FUZZY_VAL_MIN_SUB] = args->code[6]; /* Substitution minimum. */ + start_node->values[RE_FUZZY_VAL_MIN_ERR] = args->code[8]; /* Error minimum. */ + + start_node->values[RE_FUZZY_VAL_MAX_DEL] = args->code[3]; /* Deletion maximum. */ + start_node->values[RE_FUZZY_VAL_MAX_INS] = args->code[5]; /* Insertion maximum. */ + start_node->values[RE_FUZZY_VAL_MAX_SUB] = args->code[7]; /* Substitution maximum. */ + start_node->values[RE_FUZZY_VAL_MAX_ERR] = args->code[9]; /* Error maximum. */ + + start_node->values[RE_FUZZY_VAL_DEL_COST] = args->code[10]; /* Deletion cost. */ + start_node->values[RE_FUZZY_VAL_INS_COST] = args->code[11]; /* Insertion cost. */ + start_node->values[RE_FUZZY_VAL_SUB_COST] = args->code[12]; /* Substitution cost. */ + start_node->values[RE_FUZZY_VAL_MAX_COST] = args->code[13]; /* Total cost. */ + + args->code += 14; + + if (is_ext) { + subargs = *args; + status = build_charset_equiv(&subargs); + if (status != RE_ERROR_SUCCESS) + return status; + args->code = subargs.code; + if (args->code >= args->end_code || args->code[0] != RE_OP_NEXT) + return RE_ERROR_ILLEGAL; + ++args->code; + test_node = subargs.start; + } else + test_node = NULL; + + subargs = *args; + subargs.within_fuzzy = TRUE; + + /* Compile the sequence and check that we've reached the end of the + * subpattern. + */ + status = build_sequence(&subargs); + if (status != RE_ERROR_SUCCESS) + return status; + + if (subargs.code[0] != RE_OP_END) + return RE_ERROR_ILLEGAL; + + args->code = subargs.code; + args->min_width += subargs.min_width; + args->has_captures |= subargs.has_captures; + args->is_fuzzy = TRUE; + args->has_groups |= subargs.has_groups; + args->has_repeats |= subargs.has_repeats; + args->visible_capture_count = subargs.visible_capture_count; + + ++args->code; + + /* Append the fuzzy sequence. */ + add_node(args->end, start_node); + add_node(start_node, subargs.start); + if (test_node) { + add_node(start_node, test_node); + /* The END_FUZZY node needs access to the charset, if any, in case of + fuzzy insertion at the end. + */ + end_node->nonstring.next_2.node = start_node; + } + add_node(subargs.end, end_node); + args->end = end_node; + args->all_atomic = FALSE; + + return RE_ERROR_SUCCESS; +} + +/* Builds an ATOMIC node. */ +Py_LOCAL_INLINE(int) build_ATOMIC(RE_CompileArgs* args) { + RE_Node* atomic_node; + RE_CompileArgs subargs; + int status; + RE_Node* end_node; + + /* codes: opcode, ..., end. */ + if (args->code + 1 > args->end_code) + return RE_ERROR_ILLEGAL; + + atomic_node = create_node(args->pattern, RE_OP_ATOMIC, 0, 0, 0); + if (!atomic_node) + return RE_ERROR_MEMORY; + + ++args->code; + + /* Compile the sequence and check that we've reached the end of it. */ + subargs = *args; + + status = build_sequence(&subargs); + if (status != RE_ERROR_SUCCESS) + return status; + + if (subargs.code[0] != RE_OP_END) + return RE_ERROR_ILLEGAL; + + args->code = subargs.code; + args->min_width += subargs.min_width; + args->has_captures |= subargs.has_captures; + args->is_fuzzy |= subargs.is_fuzzy; + args->has_groups |= subargs.has_groups; + args->has_repeats |= subargs.has_repeats; + args->visible_capture_count = subargs.visible_capture_count; + + ++args->code; + + /* Check the subpattern. */ + if (subargs.has_groups) + atomic_node->status |= RE_STATUS_HAS_GROUPS; + + if (subargs.has_repeats) + atomic_node->status |= RE_STATUS_HAS_REPEATS; + + /* Create the node to terminate the subpattern. */ + end_node = create_node(subargs.pattern, RE_OP_END_ATOMIC, 0, 0, 0); + if (!end_node) + return RE_ERROR_MEMORY; + + /* Append the new sequence. */ + add_node(args->end, atomic_node); + add_node(atomic_node, subargs.start); + add_node(subargs.end, end_node); + args->end = end_node; + + return RE_ERROR_SUCCESS; +} + +/* Builds a BOUNDARY node. */ +Py_LOCAL_INLINE(int) build_BOUNDARY(RE_CompileArgs* args) { + RE_UINT8 op; + RE_CODE flags; + RE_Node* node; + + /* codes: opcode, flags. */ + if (args->code + 1 > args->end_code) + return RE_ERROR_ILLEGAL; + + op = (RE_UINT8)args->code[0]; + flags = args->code[1]; + + args->code += 2; + + /* Create the node. */ + node = create_node(args->pattern, op, flags, 0, 0); + if (!node) + return RE_ERROR_MEMORY; + + /* Append the node. */ + add_node(args->end, node); + args->end = node; + + return RE_ERROR_SUCCESS; +} + +/* Builds a BRANCH node. */ +Py_LOCAL_INLINE(int) build_BRANCH(RE_CompileArgs* args) { + RE_Node* branch_node; + RE_Node* join_node; + Py_ssize_t min_width; + RE_CompileArgs subargs; + int status; + + /* codes: opcode, ..., next, ..., end. */ + if (args->code + 2 > args->end_code) + return RE_ERROR_ILLEGAL; + + /* Create nodes for the start and end of the branch sequence. */ + branch_node = create_node(args->pattern, RE_OP_BRANCH, 0, 0, 0); + join_node = create_node(args->pattern, RE_OP_BRANCH, 0, 0, 0); + if (!branch_node || !join_node) + return RE_ERROR_MEMORY; + + /* Append the node. */ + add_node(args->end, branch_node); + args->end = join_node; + + min_width = PY_SSIZE_T_MAX; + + subargs = *args; + + /* A branch in the regular expression is compiled into a series of 2-way + * branches. + */ + do { + RE_Node* next_branch_node; + + /* Skip over the 'BRANCH' or 'NEXT' opcode. */ + ++subargs.code; + + /* Compile the sequence until the next 'BRANCH' or 'NEXT' opcode. */ + status = build_sequence(&subargs); + if (status != RE_ERROR_SUCCESS) + return status; + + min_width = min_ssize_t(min_width, subargs.min_width); + + args->has_captures |= subargs.has_captures; + args->is_fuzzy |= subargs.is_fuzzy; + args->has_groups |= subargs.has_groups; + args->has_repeats |= subargs.has_repeats; + + /* Append the sequence. */ + add_node(branch_node, subargs.start); + add_node(subargs.end, join_node); + + /* Create a start node for the next sequence and append it. */ + next_branch_node = create_node(subargs.pattern, RE_OP_BRANCH, 0, 0, 0); + if (!next_branch_node) + return RE_ERROR_MEMORY; + + add_node(branch_node, next_branch_node); + branch_node = next_branch_node; + } while (subargs.code < subargs.end_code && subargs.code[0] == RE_OP_NEXT); + + /* We should have reached the end of the branch. */ + if (subargs.code[0] != RE_OP_END) + return RE_ERROR_ILLEGAL; + + args->code = subargs.code; + args->visible_capture_count = subargs.visible_capture_count; + + ++args->code; + args->min_width += min_width; + args->all_atomic = FALSE; + + return RE_ERROR_SUCCESS; +} + +/* Builds a CALL_REF node. */ +Py_LOCAL_INLINE(int) build_CALL_REF(RE_CompileArgs* args) { + RE_CODE call_ref; + RE_Node* start_node; + RE_Node* end_node; + RE_CompileArgs subargs; + int status; + + /* codes: opcode, call_ref. */ + if (args->code + 1 > args->end_code) + return RE_ERROR_ILLEGAL; + + call_ref = args->code[1]; + + args->code += 2; + + /* Create nodes for the start and end of the subpattern. */ + start_node = create_node(args->pattern, RE_OP_CALL_REF, 0, 0, 1); + end_node = create_node(args->pattern, RE_OP_GROUP_RETURN, 0, 0, 0); + if (!start_node || !end_node) + return RE_ERROR_MEMORY; + + start_node->values[0] = call_ref; + + /* Compile the sequence and check that we've reached the end of the + * subpattern. + */ + subargs = *args; + status = build_sequence(&subargs); + if (status != RE_ERROR_SUCCESS) + return status; + + if (subargs.code[0] != RE_OP_END) + return RE_ERROR_ILLEGAL; + + args->code = subargs.code; + args->min_width += subargs.min_width; + args->has_captures |= subargs.has_captures; + args->is_fuzzy |= subargs.is_fuzzy; + args->has_groups |= subargs.has_groups; + args->has_repeats |= subargs.has_repeats; + args->visible_capture_count = subargs.visible_capture_count; + + ++args->code; + + /* Record that we defined a call_ref. */ + if (!record_call_ref_defined(args->pattern, call_ref, start_node)) + return RE_ERROR_MEMORY; + + /* Append the node. */ + add_node(args->end, start_node); + add_node(start_node, subargs.start); + add_node(subargs.end, end_node); + args->end = end_node; + args->all_atomic = FALSE; + + return RE_ERROR_SUCCESS; +} + +/* Builds a CHARACTER or PROPERTY node. */ +Py_LOCAL_INLINE(int) build_CHARACTER_or_PROPERTY(RE_CompileArgs* args) { + RE_UINT8 op; + RE_CODE flags; + Py_ssize_t step; + RE_Node* node; + + /* codes: opcode, flags, value. */ + if (args->code + 2 > args->end_code) + return RE_ERROR_ILLEGAL; + + op = (RE_UINT8)args->code[0]; + flags = args->code[1]; + + step = get_step(op); + + if (flags & RE_ZEROWIDTH_OP) + step = 0; + + /* Create the node. */ + node = create_node(args->pattern, op, flags, step, 1); + if (!node) + return RE_ERROR_MEMORY; + + node->values[0] = args->code[2]; + + args->code += 3; + + /* Append the node. */ + add_node(args->end, node); + args->end = node; + + if (step != 0) + ++args->min_width; + + return RE_ERROR_SUCCESS; +} + +/* Builds a CONDITIONAL node. */ +Py_LOCAL_INLINE(int) build_CONDITIONAL(RE_CompileArgs* args) { + RE_CODE flags; + BOOL forward; + RE_Node* test_node; + RE_CompileArgs subargs; + int status; + RE_Node* end_test_node; + RE_Node* end_node; + Py_ssize_t min_width; + + /* codes: opcode, flags, forward, ..., next, ..., next, ..., end. */ + if (args->code + 4 > args->end_code) + return RE_ERROR_ILLEGAL; + + flags = args->code[1]; + forward = (BOOL)args->code[2]; + + /* Create a node for the lookaround. */ + test_node = create_node(args->pattern, RE_OP_CONDITIONAL, flags, 0, 0); + if (!test_node) + return RE_ERROR_MEMORY; + + args->code += 3; + + add_node(args->end, test_node); + + /* Compile the lookaround test and check that we've reached the end of the + * subpattern. + */ + subargs = *args; + subargs.forward = forward; + status = build_sequence(&subargs); + if (status != RE_ERROR_SUCCESS) + return status; + + if (subargs.code[0] != RE_OP_NEXT) + return RE_ERROR_ILLEGAL; + + args->code = subargs.code; + args->has_captures |= subargs.has_captures; + args->is_fuzzy |= subargs.is_fuzzy; + args->has_groups |= subargs.has_groups; + args->has_repeats |= subargs.has_repeats; + args->visible_capture_count = subargs.visible_capture_count; + + ++args->code; + + /* Check the lookaround subpattern. */ + if (subargs.has_groups) + test_node->status |= RE_STATUS_HAS_GROUPS; + + if (subargs.has_repeats) + test_node->status |= RE_STATUS_HAS_REPEATS; + + /* Create the node to terminate the test. */ + end_test_node = create_node(args->pattern, RE_OP_END_CONDITIONAL, 0, 0, 0); + if (!end_test_node) + return RE_ERROR_MEMORY; + + /* test node -> test -> end test node */ + add_node(test_node, subargs.start); + add_node(subargs.end, end_test_node); + + /* Compile the true branch. */ + subargs = *args; + status = build_sequence(&subargs); + if (status != RE_ERROR_SUCCESS) + return status; + + /* Check the true branch. */ + args->code = subargs.code; + args->has_captures |= subargs.has_captures; + args->is_fuzzy |= subargs.is_fuzzy; + args->has_groups |= subargs.has_groups; + args->has_repeats |= subargs.has_repeats; + args->visible_capture_count = subargs.visible_capture_count; + + min_width = subargs.min_width; + + /* Create the terminating node. */ + end_node = create_node(args->pattern, RE_OP_BRANCH, 0, 0, 0); + if (!end_node) + return RE_ERROR_MEMORY; + + /* end test node -> true branch -> end node */ + add_node(end_test_node, subargs.start); + add_node(subargs.end, end_node); + test_node->nonstring.true_node = subargs.start; + + if (args->code[0] == RE_OP_NEXT) { + /* There's a false branch. */ + ++args->code; + + /* Compile the false branch. */ + subargs.code = args->code; + status = build_sequence(&subargs); + if (status != RE_ERROR_SUCCESS) + return status; + + /* Check the false branch. */ + args->code = subargs.code; + args->has_captures |= subargs.has_captures; + args->is_fuzzy |= subargs.is_fuzzy; + args->has_groups |= subargs.has_groups; + args->has_repeats |= subargs.has_repeats; + args->visible_capture_count = subargs.visible_capture_count; + + min_width = min_ssize_t(min_width, subargs.min_width); + + /* test node -> false branch -> end node */ + add_node(test_node, subargs.start); + add_node(subargs.end, end_node); + } else { + min_width = 0; + + /* test node -> end node */ + add_node(test_node, end_node); + } + + if (args->code[0] != RE_OP_END) + return RE_ERROR_ILLEGAL; + + args->min_width += min_width; + + ++args->code; + + args->end = end_node; + args->all_atomic = FALSE; + + return RE_ERROR_SUCCESS; +} + +/* Builds a GROUP node. */ +Py_LOCAL_INLINE(int) build_GROUP(RE_CompileArgs* args) { + BOOL forward; + RE_CODE private_group; + RE_CODE public_group; + RE_Node* start_node; + RE_Node* end_node; + RE_CompileArgs subargs; + int status; + + /* codes: opcode, forward, private_group, public_group, ..., end. */ + if (args->code + 3 > args->end_code) + return RE_ERROR_ILLEGAL; + + forward = (BOOL)args->code[1]; + private_group = args->code[2]; + public_group = args->code[3]; + + args->code += 4; + + /* Create nodes for the start and end of the capture group. */ + start_node = create_node(args->pattern, forward ? RE_OP_START_GROUP : + RE_OP_END_GROUP, 0, 0, 3); + end_node = create_node(args->pattern, forward ? RE_OP_END_GROUP : + RE_OP_START_GROUP, 0, 0, 3); + if (!start_node || !end_node) + return RE_ERROR_MEMORY; + + start_node->values[0] = private_group; + end_node->values[0] = private_group; + start_node->values[1] = public_group; + end_node->values[1] = public_group; + + /* Signal that the capture should be saved when it's complete. */ + start_node->values[2] = 0; + end_node->values[2] = 1; + + /* Record that we have a new capture group. */ + if (!record_group(args->pattern, private_group, start_node)) + return RE_ERROR_MEMORY; + + /* Compile the sequence and check that we've reached the end of the capture + * group. + */ + subargs = *args; + status = build_sequence(&subargs); + if (status != RE_ERROR_SUCCESS) + return status; + + if (subargs.code[0] != RE_OP_END) + return RE_ERROR_ILLEGAL; + + args->code = subargs.code; + args->min_width += subargs.min_width; + args->has_captures |= subargs.has_captures | subargs.visible_captures; + args->is_fuzzy |= subargs.is_fuzzy; + args->has_groups |= TRUE; + args->has_repeats |= subargs.has_repeats; + args->visible_capture_count = subargs.visible_capture_count; + + if (!args->in_define) + ++args->visible_capture_count; + + ++args->code; + + /* Record that the capture group has closed. */ + record_group_end(args->pattern, private_group); + + /* Append the capture group. */ + add_node(args->end, start_node); + add_node(start_node, subargs.start); + add_node(subargs.end, end_node); + args->end = end_node; + + return RE_ERROR_SUCCESS; +} + +/* Builds a GROUP_CALL node. */ +Py_LOCAL_INLINE(int) build_GROUP_CALL(RE_CompileArgs* args) { + RE_CODE call_ref; + RE_Node* node; + + /* codes: opcode, call_ref. */ + if (args->code + 1 > args->end_code) + return RE_ERROR_ILLEGAL; + + call_ref = args->code[1]; + + /* Create the node. */ + node = create_node(args->pattern, RE_OP_GROUP_CALL, 0, 0, 1); + if (!node) + return RE_ERROR_MEMORY; + + node->values[0] = call_ref; + + node->status |= RE_STATUS_HAS_GROUPS; + node->status |= RE_STATUS_HAS_REPEATS; + + args->code += 2; + + /* Record that we used a call_ref. */ + if (!record_call_ref_used(args->pattern, call_ref)) + return RE_ERROR_MEMORY; + + /* Append the node. */ + add_node(args->end, node); + args->end = node; + args->all_atomic = FALSE; + + return RE_ERROR_SUCCESS; +} + +/* Builds a GROUP_EXISTS node. */ +Py_LOCAL_INLINE(int) build_GROUP_EXISTS(RE_CompileArgs* args) { + RE_CODE group; + RE_Node* start_node; + RE_Node* end_node; + RE_CompileArgs subargs; + int status; + Py_ssize_t min_width; + + /* codes: opcode, ..., next, ..., end. */ + if (args->code + 2 > args->end_code) + return RE_ERROR_ILLEGAL; + + group = args->code[1]; + + args->code += 2; + + /* Record that we have a reference to a group. If group is 0, then we have + * a DEFINE and not a true group. + */ + if (group > 0 && !record_ref_group(args->pattern, group)) + return RE_ERROR_MEMORY; + + /* Create nodes for the start and end of the structure. */ + start_node = create_node(args->pattern, RE_OP_GROUP_EXISTS, 0, 0, 1); + end_node = create_node(args->pattern, RE_OP_BRANCH, 0, 0, 0); + if (!start_node || !end_node) + return RE_ERROR_MEMORY; + + start_node->values[0] = group; + + subargs = *args; + subargs.in_define = TRUE; + status = build_sequence(&subargs); + if (status != RE_ERROR_SUCCESS) + return status; + + args->code = subargs.code; + args->has_captures |= subargs.has_captures; + args->is_fuzzy |= subargs.is_fuzzy; + args->has_groups |= subargs.has_groups; + args->has_repeats |= subargs.has_repeats; + args->visible_capture_count = subargs.visible_capture_count; + + min_width = subargs.min_width; + + /* Append the start node. */ + add_node(args->end, start_node); + add_node(start_node, subargs.start); + + if (args->code[0] == RE_OP_NEXT) { + RE_Node* true_branch_end; + + ++args->code; + + true_branch_end = subargs.end; + + subargs.code = args->code; + + status = build_sequence(&subargs); + if (status != RE_ERROR_SUCCESS) + return status; + + args->code = subargs.code; + args->has_captures |= subargs.has_captures; + args->is_fuzzy |= subargs.is_fuzzy; + args->visible_capture_count = subargs.visible_capture_count; + + if (group == 0) { + /* Join the 2 branches end-to-end and bypass it. The sequence + * itself will never be matched as a whole, so it doesn't matter. + */ + min_width = 0; + + add_node(start_node, end_node); + add_node(true_branch_end, subargs.start); + } else { + args->has_groups |= subargs.has_groups; + args->has_repeats |= subargs.has_repeats; + args->visible_capture_count = subargs.visible_capture_count; + + min_width = min_ssize_t(min_width, subargs.min_width); + + add_node(start_node, subargs.start); + add_node(true_branch_end, end_node); + } + + add_node(subargs.end, end_node); + } else { + add_node(start_node, end_node); + add_node(subargs.end, end_node); + + min_width = 0; + } + + args->min_width += min_width; + + if (args->code[0] != RE_OP_END) + return RE_ERROR_ILLEGAL; + + ++args->code; + + args->end = end_node; + args->all_atomic = FALSE; + + return RE_ERROR_SUCCESS; +} + +/* Builds a LOOKAROUND node. */ +Py_LOCAL_INLINE(int) build_LOOKAROUND(RE_CompileArgs* args) { + RE_CODE flags; + BOOL forward; + RE_Node* lookaround_node; + RE_CompileArgs subargs; + int status; + RE_Node* end_node; + RE_Node* next_node; + + /* codes: opcode, flags, forward, ..., end. */ + if (args->code + 3 > args->end_code) + return RE_ERROR_ILLEGAL; + + flags = args->code[1]; + forward = (BOOL)args->code[2]; + + /* Create a node for the lookaround. */ + lookaround_node = create_node(args->pattern, RE_OP_LOOKAROUND, flags, 0, + 0); + if (!lookaround_node) + return RE_ERROR_MEMORY; + + args->code += 3; + + /* Compile the sequence and check that we've reached the end of the + * subpattern. + */ + subargs = *args; + subargs.forward = forward; + status = build_sequence(&subargs); + if (status != RE_ERROR_SUCCESS) + return status; + + if (subargs.code[0] != RE_OP_END) + return RE_ERROR_ILLEGAL; + + args->code = subargs.code; + ++args->code; + + /* Check the subpattern. */ + args->has_captures |= subargs.has_captures; + args->is_fuzzy |= subargs.is_fuzzy; + args->has_groups |= subargs.has_groups; + args->has_repeats |= subargs.has_repeats; + args->visible_capture_count = subargs.visible_capture_count; + + if (subargs.has_groups) + lookaround_node->status |= RE_STATUS_HAS_GROUPS; + + if (subargs.has_repeats) + lookaround_node->status |= RE_STATUS_HAS_REPEATS; + + /* Create the node to terminate the subpattern. */ + end_node = create_node(args->pattern, RE_OP_END_LOOKAROUND, 0, 0, 0); + if (!end_node) + return RE_ERROR_MEMORY; + + /* Make a continuation node. */ + next_node = create_node(args->pattern, RE_OP_BRANCH, 0, 0, 0); + if (!next_node) + return RE_ERROR_MEMORY; + + /* Append the new sequence. */ + add_node(args->end, lookaround_node); + add_node(lookaround_node, subargs.start); + add_node(lookaround_node, next_node); + add_node(subargs.end, end_node); + add_node(end_node, next_node); + + args->end = next_node; + args->all_atomic = FALSE; + + return RE_ERROR_SUCCESS; +} + +/* Builds a RANGE node. */ +Py_LOCAL_INLINE(int) build_RANGE(RE_CompileArgs* args) { + RE_UINT8 op; + RE_CODE flags; + Py_ssize_t step; + RE_Node* node; + + /* codes: opcode, flags, lower, upper. */ + if (args->code + 3 > args->end_code) + return RE_ERROR_ILLEGAL; + + op = (RE_UINT8)args->code[0]; + flags = args->code[1]; + + step = get_step(op); + + if (flags & RE_ZEROWIDTH_OP) + step = 0; + + /* Create the node. */ + node = create_node(args->pattern, op, flags, step, 2); + if (!node) + return RE_ERROR_MEMORY; + + node->values[0] = args->code[2]; + node->values[1] = args->code[3]; + + args->code += 4; + + /* Append the node. */ + add_node(args->end, node); + args->end = node; + + if (step != 0) + ++args->min_width; + + return RE_ERROR_SUCCESS; +} + +/* Builds a REF_GROUP node. */ +Py_LOCAL_INLINE(int) build_REF_GROUP(RE_CompileArgs* args) { + RE_CODE flags; + RE_CODE group; + RE_Node* node; + + /* codes: opcode, flags, group. */ + if (args->code + 2 > args->end_code) + return RE_ERROR_ILLEGAL; + + flags = args->code[1]; + group = args->code[2]; + node = create_node(args->pattern, (RE_UINT8)args->code[0], flags, 0, 1); + if (!node) + return RE_ERROR_MEMORY; + + node->values[0] = group; + + args->code += 3; + + /* Record that we have a reference to a group. */ + if (!record_ref_group(args->pattern, group)) + return RE_ERROR_MEMORY; + + /* Append the reference. */ + add_node(args->end, node); + args->end = node; + + return RE_ERROR_SUCCESS; +} + +/* Builds a REPEAT node. */ +Py_LOCAL_INLINE(int) build_REPEAT(RE_CompileArgs* args) { + BOOL greedy; + RE_CODE min_count; + RE_CODE max_count; + int status; + + /* codes: opcode, min_count, max_count, ..., end. */ + if (args->code + 3 > args->end_code) + return RE_ERROR_ILLEGAL; + + greedy = args->code[0] == RE_OP_GREEDY_REPEAT; + min_count = args->code[1]; + max_count = args->code[2]; + if (args->code[1] > args->code[2]) + return RE_ERROR_ILLEGAL; + + args->code += 3; + + if (min_count == 1 && max_count == 1) { + /* Singly-repeated sequence. */ + RE_CompileArgs subargs; + + subargs = *args; + status = build_sequence(&subargs); + if (status != RE_ERROR_SUCCESS) + return status; + + if (subargs.code[0] != RE_OP_END) + return RE_ERROR_ILLEGAL; + + args->code = subargs.code; + args->min_width += subargs.min_width; + args->has_captures |= subargs.has_captures; + args->is_fuzzy |= subargs.is_fuzzy; + args->has_groups |= subargs.has_groups; + args->has_repeats |= subargs.has_repeats; + args->visible_capture_count = subargs.visible_capture_count; + + ++args->code; + + /* Append the sequence. */ + add_node(args->end, subargs.start); + args->end = subargs.end; + } else { + /* Extract the minimum number of repeats out of a repeat if it contains + * a repeat. + */ + size_t index; + RE_Node* repeat_node; + RE_CompileArgs subargs; + + if (min_count > 0) { + RE_CODE done_count; + + for (done_count = 0; done_count < min_count; done_count++) { + subargs = *args; + subargs.visible_captures = TRUE; + + status = build_sequence(&subargs); + if (status != RE_ERROR_SUCCESS) + return status; + + if (subargs.code[0] != RE_OP_END) + return RE_ERROR_ILLEGAL; + + args->visible_capture_count = subargs.visible_capture_count; + + add_node(args->end, subargs.start); + args->end = subargs.end; + } + + args->min_width += (Py_ssize_t)min_count * subargs.min_width; + args->has_captures |= subargs.has_captures; + args->is_fuzzy |= subargs.is_fuzzy; + args->has_groups |= subargs.has_groups; + args->has_repeats |= subargs.has_repeats; + + min_count -= done_count; + if (~max_count != 0) + max_count -= done_count; + } + + /* We've extracted the minimum number of repeats. Are there any left? */ + if (min_count > 0 && max_count == 0) { + /* All done. */ + args->code = subargs.code; + ++args->code; + } else { + /* More to do. */ + index = args->pattern->repeat_count; + + /* Create the nodes for the repeat. */ + repeat_node = create_node(args->pattern, greedy ? + RE_OP_GREEDY_REPEAT : RE_OP_LAZY_REPEAT, 0, args->forward ? 1 : + -1, 4); + if (!repeat_node || !record_repeat(args->pattern, index, + args->repeat_depth)) + return RE_ERROR_MEMORY; + + repeat_node->values[0] = (RE_CODE)index; + repeat_node->values[1] = min_count; + repeat_node->values[2] = max_count; + repeat_node->values[3] = args->forward; + + if (args->within_fuzzy) + args->pattern->repeat_info[index].status |= RE_STATUS_BODY; + + /* Compile the 'body' and check that we've reached the end of it. + */ + subargs = *args; + subargs.visible_captures = TRUE; + ++subargs.repeat_depth; + status = build_sequence(&subargs); + if (status != RE_ERROR_SUCCESS) + return status; + + if (subargs.code[0] != RE_OP_END) + return RE_ERROR_ILLEGAL; + + args->code = subargs.code; + args->min_width += (Py_ssize_t)min_count * subargs.min_width; + args->has_captures |= subargs.has_captures; + args->is_fuzzy |= subargs.is_fuzzy; + args->has_groups |= subargs.has_groups; + args->has_repeats = TRUE; + args->visible_capture_count = subargs.visible_capture_count; + + ++args->code; + + /* Is it a repeat of something which will match a single character? + * + * If it's in a fuzzy section then it won't be optimised as a + * single-character repeat. + */ + if (sequence_matches_one(subargs.start)) { + repeat_node->op = greedy ? RE_OP_GREEDY_REPEAT_ONE : + RE_OP_LAZY_REPEAT_ONE; + + if (args->all_atomic && args->code < args->end_code && + args->code[0] == RE_OP_END && !args->within_fuzzy) + repeat_node->status |= RE_STATUS_ALL_ATOMIC; + + /* Append the new sequence. */ + add_node(args->end, repeat_node); + repeat_node->nonstring.next_2.node = subargs.start; + args->end = repeat_node; + } else { + RE_Node* end_repeat_node; + RE_Node* end_node; + + end_repeat_node = create_node(args->pattern, greedy ? + RE_OP_END_GREEDY_REPEAT : RE_OP_END_LAZY_REPEAT, 0, + args->forward ? 1 : -1, 4); + if (!end_repeat_node) + return RE_ERROR_MEMORY; + + end_repeat_node->values[0] = repeat_node->values[0]; + end_repeat_node->values[1] = repeat_node->values[1]; + end_repeat_node->values[2] = repeat_node->values[2]; + end_repeat_node->values[3] = args->forward; + + end_node = create_node(args->pattern, RE_OP_BRANCH, 0, 0, 0); + if (!end_node) + return RE_ERROR_MEMORY; + + if (args->all_atomic && args->code < args->end_code && + args->code[0] == RE_OP_END && !args->within_fuzzy) + end_repeat_node->status |= RE_STATUS_ALL_ATOMIC; + + /* Append the new sequence. */ + add_node(args->end, repeat_node); + add_node(repeat_node, subargs.start); + add_node(repeat_node, end_node); + add_node(subargs.end, end_repeat_node); + add_node(end_repeat_node, subargs.start); + add_node(end_repeat_node, end_node); + args->end = end_node; + } + } + } + + if (!(args->all_atomic && args->code < args->end_code && args->code[0] != + RE_OP_END && !args->within_fuzzy)) + args->all_atomic = FALSE; + + return RE_ERROR_SUCCESS; +} + +/* Builds a STRING node. */ +Py_LOCAL_INLINE(int) build_STRING(RE_CompileArgs* args, BOOL is_charset) { + RE_CODE flags; + RE_CODE length; + RE_UINT8 op; + Py_ssize_t step; + RE_Node* node; + size_t i; + + /* codes: opcode, flags, length, .... */ + flags = args->code[1]; + length = args->code[2]; + if (args->code + 3 + length > args->end_code) + return RE_ERROR_ILLEGAL; + + op = (RE_UINT8)args->code[0]; + + step = get_step(op); + + /* Create the node. */ + node = create_node(args->pattern, op, flags, step * (Py_ssize_t)length, + length); + if (!node) + return RE_ERROR_MEMORY; + if (!is_charset) + node->status |= RE_STATUS_STRING; + + for (i = 0; i < length; i++) + node->values[i] = args->code[3 + i]; + + args->code += 3 + length; + + /* Append the node. */ + add_node(args->end, node); + args->end = node; + + /* Because of full case-folding, one character in the text could match + * multiple characters in the pattern. + */ + if (op == RE_OP_STRING_FLD || op == RE_OP_STRING_FLD_REV) + args->min_width += possible_unfolded_length((Py_ssize_t)length); + else + args->min_width += (Py_ssize_t)length; + + return RE_ERROR_SUCCESS; +} + +/* Builds a SET node. */ +Py_LOCAL_INLINE(int) build_SET(RE_CompileArgs* args) { + RE_UINT8 op; + RE_CODE flags; + Py_ssize_t step; + RE_Node* node; + Py_ssize_t min_width; + int status; + + /* codes: opcode, flags, ..., end. */ + op = (RE_UINT8)args->code[0]; + flags = args->code[1]; + + step = get_step(op); + + if (flags & RE_ZEROWIDTH_OP) + step = 0; + + node = create_node(args->pattern, op, flags, step, 0); + if (!node) + return RE_ERROR_MEMORY; + + args->code += 2; + + /* Append the node. */ + add_node(args->end, node); + args->end = node; + + min_width = args->min_width; + + /* Compile the character set. */ + do { + switch (args->code[0]) { + case RE_OP_CHARACTER: + case RE_OP_PROPERTY: + status = build_CHARACTER_or_PROPERTY(args); + if (status != RE_ERROR_SUCCESS) + return status; + break; + case RE_OP_RANGE: + status = build_RANGE(args); + if (status != RE_ERROR_SUCCESS) + return status; + break; + case RE_OP_SET_DIFF: + case RE_OP_SET_INTER: + case RE_OP_SET_SYM_DIFF: + case RE_OP_SET_UNION: + status = build_SET(args); + if (status != RE_ERROR_SUCCESS) + return status; + break; + case RE_OP_STRING: + /* A set of characters. */ + status = build_STRING(args, TRUE); + if (status != RE_ERROR_SUCCESS) + return status; + break; + default: + /* Illegal opcode for a character set. */ + return RE_ERROR_ILLEGAL; + } + } while (args->code < args->end_code && args->code[0] != RE_OP_END); + + /* Check that we've reached the end correctly. (The last opcode should be + * 'END'.) + */ + if (args->code >= args->end_code || args->code[0] != RE_OP_END) + return RE_ERROR_ILLEGAL; + + ++args->code; + + /* At this point the set's members are in the main sequence. They need to + * be moved out-of-line. + */ + node->nonstring.next_2.node = node->next_1.node; + node->next_1.node = NULL; + args->end = node; + + args->min_width = min_width; + + if (step != 0) + ++args->min_width; + + return RE_ERROR_SUCCESS; +} + +/* Builds a SUCCESS node . */ +Py_LOCAL_INLINE(int) build_SUCCESS(RE_CompileArgs* args) { + RE_Node* node; + /* codes: opcode. */ + + /* Create the node. */ + node = create_node(args->pattern, (RE_UINT8)args->code[0], 0, 0, 0); + if (!node) + return RE_ERROR_MEMORY; + + ++args->code; + + /* Append the node. */ + add_node(args->end, node); + args->end = node; + + return RE_ERROR_SUCCESS; +} + +/* Builds a zero-width node. */ +Py_LOCAL_INLINE(int) build_zerowidth(RE_CompileArgs* args) { + RE_CODE flags; + RE_Node* node; + + /* codes: opcode, flags. */ + if (args->code + 1 > args->end_code) + return RE_ERROR_ILLEGAL; + + flags = args->code[1]; + + /* Create the node. */ + node = create_node(args->pattern, (RE_UINT8)args->code[0], flags, 0, 0); + if (!node) + return RE_ERROR_MEMORY; + + args->code += 2; + + /* Append the node. */ + add_node(args->end, node); + args->end = node; + + return RE_ERROR_SUCCESS; +} + +/* Builds a node that's equivalent to a character set. */ +Py_LOCAL_INLINE(int) build_charset_equiv(RE_CompileArgs* args) { + int status; + + /* Guarantee that there's something to attach to. */ + args->start = create_node(args->pattern, RE_OP_BRANCH, 0, 0, 0); + args->end = args->start; + + /* The following code groups opcodes by format, not function. */ + switch (args->code[0]) { + case RE_OP_ANY: + case RE_OP_ANY_ALL: + case RE_OP_ANY_U: + case RE_OP_ANY_REV: + case RE_OP_ANY_ALL_REV: + case RE_OP_ANY_U_REV: + /* A simple opcode with no trailing codewords and width of 1. */ + status = build_ANY(args); + if (status != RE_ERROR_SUCCESS) + return status; + break; + case RE_OP_CHARACTER: + case RE_OP_PROPERTY: + case RE_OP_CHARACTER_IGN: + case RE_OP_PROPERTY_IGN: + case RE_OP_CHARACTER_REV: + case RE_OP_PROPERTY_REV: + case RE_OP_CHARACTER_IGN_REV: + case RE_OP_PROPERTY_IGN_REV: + /* A character literal or a property. */ + status = build_CHARACTER_or_PROPERTY(args); + if (status != RE_ERROR_SUCCESS) + return status; + break; + case RE_OP_RANGE: + case RE_OP_RANGE_IGN: + case RE_OP_RANGE_IGN_REV: + case RE_OP_RANGE_REV: + /* A range. */ + status = build_RANGE(args); + if (status != RE_ERROR_SUCCESS) + return status; + break; + case RE_OP_SET_DIFF: + case RE_OP_SET_DIFF_IGN: + case RE_OP_SET_DIFF_IGN_REV: + case RE_OP_SET_DIFF_REV: + case RE_OP_SET_INTER: + case RE_OP_SET_INTER_IGN: + case RE_OP_SET_INTER_IGN_REV: + case RE_OP_SET_INTER_REV: + case RE_OP_SET_SYM_DIFF: + case RE_OP_SET_SYM_DIFF_IGN: + case RE_OP_SET_SYM_DIFF_IGN_REV: + case RE_OP_SET_SYM_DIFF_REV: + case RE_OP_SET_UNION: + case RE_OP_SET_UNION_IGN: + case RE_OP_SET_UNION_IGN_REV: + case RE_OP_SET_UNION_REV: + /* A set. */ + status = build_SET(args); + if (status != RE_ERROR_SUCCESS) + return status; + break; + default: + /* We've found an opcode which we don't recognise. */ + return RE_ERROR_ILLEGAL; + } + + return RE_ERROR_SUCCESS; +} + +/* Builds a sequence of nodes from regular expression code. */ +Py_LOCAL_INLINE(int) build_sequence(RE_CompileArgs* args) { + int status; + + /* Guarantee that there's something to attach to. */ + args->start = create_node(args->pattern, RE_OP_BRANCH, 0, 0, 0); + args->end = args->start; + + args->min_width = 0; + args->has_captures = FALSE; + args->is_fuzzy = FALSE; + args->has_groups = FALSE; + args->has_repeats = FALSE; + args->all_atomic = TRUE; + + /* The sequence should end with an opcode we don't understand. If it + * doesn't then the code is illegal. + */ + while (args->code < args->end_code) { + /* The following code groups opcodes by format, not function. */ + switch (args->code[0]) { + case RE_OP_ANY: + case RE_OP_ANY_ALL: + case RE_OP_ANY_ALL_REV: + case RE_OP_ANY_REV: + case RE_OP_ANY_U: + case RE_OP_ANY_U_REV: + /* A simple opcode with no trailing codewords and width of 1. */ + status = build_ANY(args); + if (status != RE_ERROR_SUCCESS) + return status; + break; + case RE_OP_ATOMIC: + /* An atomic sequence. */ + status = build_ATOMIC(args); + if (status != RE_ERROR_SUCCESS) + return status; + break; + case RE_OP_BOUNDARY: + case RE_OP_DEFAULT_BOUNDARY: + case RE_OP_DEFAULT_END_OF_WORD: + case RE_OP_DEFAULT_START_OF_WORD: + case RE_OP_END_OF_WORD: + case RE_OP_GRAPHEME_BOUNDARY: + case RE_OP_KEEP: + case RE_OP_SKIP: + case RE_OP_START_OF_WORD: + /* A word or grapheme boundary. */ + status = build_BOUNDARY(args); + if (status != RE_ERROR_SUCCESS) + return status; + break; + case RE_OP_BRANCH: + /* A 2-way branch. */ + status = build_BRANCH(args); + if (status != RE_ERROR_SUCCESS) + return status; + break; + case RE_OP_CALL_REF: + /* A group call ref. */ + status = build_CALL_REF(args); + if (status != RE_ERROR_SUCCESS) + return status; + break; + case RE_OP_CHARACTER: + case RE_OP_CHARACTER_IGN: + case RE_OP_CHARACTER_IGN_REV: + case RE_OP_CHARACTER_REV: + case RE_OP_PROPERTY: + case RE_OP_PROPERTY_IGN: + case RE_OP_PROPERTY_IGN_REV: + case RE_OP_PROPERTY_REV: + /* A character literal or a property. */ + status = build_CHARACTER_or_PROPERTY(args); + if (status != RE_ERROR_SUCCESS) + return status; + break; + case RE_OP_CONDITIONAL: + /* A lookaround conditional. */ + status = build_CONDITIONAL(args); + if (status != RE_ERROR_SUCCESS) + return status; + break; + case RE_OP_END_OF_LINE: + case RE_OP_END_OF_LINE_U: + case RE_OP_END_OF_STRING: + case RE_OP_END_OF_STRING_LINE: + case RE_OP_END_OF_STRING_LINE_U: + case RE_OP_SEARCH_ANCHOR: + case RE_OP_START_OF_LINE: + case RE_OP_START_OF_LINE_U: + case RE_OP_START_OF_STRING: + /* A simple opcode with no trailing codewords and width of 0. */ + status = build_zerowidth(args); + if (status != RE_ERROR_SUCCESS) + return status; + break; + case RE_OP_FAILURE: + case RE_OP_PRUNE: + case RE_OP_SUCCESS: + status = build_SUCCESS(args); + if (status != RE_ERROR_SUCCESS) + return status; + break; + case RE_OP_FUZZY: + case RE_OP_FUZZY_EXT: + /* A fuzzy sequence. */ + status = build_FUZZY(args); + if (status != RE_ERROR_SUCCESS) + return status; + break; + case RE_OP_GREEDY_REPEAT: + case RE_OP_LAZY_REPEAT: + /* A repeated sequence. */ + status = build_REPEAT(args); + if (status != RE_ERROR_SUCCESS) + return status; + break; + case RE_OP_GROUP: + /* A capture group. */ + status = build_GROUP(args); + if (status != RE_ERROR_SUCCESS) + return status; + break; + case RE_OP_GROUP_CALL: + /* A group call. */ + status = build_GROUP_CALL(args); + if (status != RE_ERROR_SUCCESS) + return status; + break; + case RE_OP_GROUP_EXISTS: + /* A conditional sequence. */ + status = build_GROUP_EXISTS(args); + if (status != RE_ERROR_SUCCESS) + return status; + break; + case RE_OP_LOOKAROUND: + /* A lookaround. */ + status = build_LOOKAROUND(args); + if (status != RE_ERROR_SUCCESS) + return status; + break; + case RE_OP_RANGE: + case RE_OP_RANGE_IGN: + case RE_OP_RANGE_IGN_REV: + case RE_OP_RANGE_REV: + /* A range. */ + status = build_RANGE(args); + if (status != RE_ERROR_SUCCESS) + return status; + break; + case RE_OP_REF_GROUP: + case RE_OP_REF_GROUP_FLD: + case RE_OP_REF_GROUP_FLD_REV: + case RE_OP_REF_GROUP_IGN: + case RE_OP_REF_GROUP_IGN_REV: + case RE_OP_REF_GROUP_REV: + /* A reference to a group. */ + status = build_REF_GROUP(args); + if (status != RE_ERROR_SUCCESS) + return status; + break; + case RE_OP_SET_DIFF: + case RE_OP_SET_DIFF_IGN: + case RE_OP_SET_DIFF_IGN_REV: + case RE_OP_SET_DIFF_REV: + case RE_OP_SET_INTER: + case RE_OP_SET_INTER_IGN: + case RE_OP_SET_INTER_IGN_REV: + case RE_OP_SET_INTER_REV: + case RE_OP_SET_SYM_DIFF: + case RE_OP_SET_SYM_DIFF_IGN: + case RE_OP_SET_SYM_DIFF_IGN_REV: + case RE_OP_SET_SYM_DIFF_REV: + case RE_OP_SET_UNION: + case RE_OP_SET_UNION_IGN: + case RE_OP_SET_UNION_IGN_REV: + case RE_OP_SET_UNION_REV: + /* A set. */ + status = build_SET(args); + if (status != RE_ERROR_SUCCESS) + return status; + break; + case RE_OP_STRING: + case RE_OP_STRING_FLD: + case RE_OP_STRING_FLD_REV: + case RE_OP_STRING_IGN: + case RE_OP_STRING_IGN_REV: + case RE_OP_STRING_REV: + /* A string literal. */ + if (!build_STRING(args, FALSE)) + return FALSE; + break; + default: + /* We've found an opcode which we don't recognise. We'll leave it + * for the caller. + */ + return RE_ERROR_SUCCESS; + } + } + + /* If we're here then we should be at the end of the code, otherwise we + * have an error. + */ + return args->code == args->end_code; +} + +/* Compiles the regular expression code to 'nodes'. + * + * Various details about the regular expression are discovered during + * compilation and stored in the PatternObject. + */ +Py_LOCAL_INLINE(BOOL) compile_to_nodes(RE_CODE* code, RE_CODE* end_code, + PatternObject* pattern) { + RE_CompileArgs args; + int status; + + /* Compile a regex sequence and then check that we've reached the end + * correctly. (The last opcode should be 'SUCCESS'.) + * + * If successful, 'start' and 'end' will point to the start and end nodes + * of the compiled sequence. + */ + args.code = code; + args.end_code = end_code; + args.pattern = pattern; + args.forward = (pattern->flags & RE_FLAG_REVERSE) == 0; + args.visible_captures = FALSE; + args.has_captures = FALSE; + args.repeat_depth = 0; + args.is_fuzzy = FALSE; + args.within_fuzzy = FALSE; + args.visible_capture_count = 0; + args.in_define = FALSE; + status = build_sequence(&args); + if (status == RE_ERROR_ILLEGAL) + set_error(RE_ERROR_ILLEGAL, NULL); + + if (status != RE_ERROR_SUCCESS) + return FALSE; + + pattern->min_width = args.min_width; + pattern->is_fuzzy = args.is_fuzzy; + pattern->do_search_start = TRUE; + pattern->start_node = args.start; + pattern->visible_capture_count = args.visible_capture_count; + + /* Optimise the pattern. */ + if (!optimise_pattern(pattern)) + return FALSE; + + pattern->start_test = locate_test_start(pattern->start_node); + + /* Get the call_ref for the entire pattern, if any. */ + if (pattern->start_node->op == RE_OP_CALL_REF) + pattern->pattern_call_ref = (Py_ssize_t)pattern->start_node->values[0]; + else + pattern->pattern_call_ref = -1; + + return TRUE; +} + +/* Gets the required characters for a regex. + * + * In the event of an error, it just pretends that there are no required + * characters. + */ +Py_LOCAL_INLINE(void) get_required_chars(PyObject* required_chars, RE_CODE** + req_chars, size_t* req_length) { + Py_ssize_t len; + RE_CODE* chars; + Py_ssize_t i; + + *req_chars = NULL; + *req_length = 0; + + len = PyTuple_GET_SIZE(required_chars); + if (len < 1 || PyErr_Occurred()) { + PyErr_Clear(); + return; + } + + chars = (RE_CODE*)re_alloc((size_t)len * sizeof(RE_CODE)); + if (!chars) + goto error; + + for (i = 0; i < len; i++) { + PyObject* o; + size_t value; + + /* PyTuple_SET_ITEM borrows the reference. */ + o = PyTuple_GET_ITEM(required_chars, i); + + value = PyLong_AsUnsignedLong(o); + if ((Py_ssize_t)value == -1 && PyErr_Occurred()) + goto error; + + chars[i] = (RE_CODE)value; + if (chars[i] != value) + goto error; + } + + *req_chars = chars; + *req_length = (size_t)len; + + return; + +error: + PyErr_Clear(); + re_dealloc(chars); +} + +/* Makes a STRING node. */ +Py_LOCAL_INLINE(RE_Node*) make_STRING_node(PatternObject* pattern, RE_UINT8 op, + size_t length, RE_CODE* chars) { + Py_ssize_t step; + RE_Node* node; + size_t i; + + step = get_step(op); + + /* Create the node. */ + node = create_node(pattern, op, 0, step * (Py_ssize_t)length, length); + if (!node) + return NULL; + + node->status |= RE_STATUS_STRING; + + for (i = 0; i < length; i++) + node->values[i] = chars[i]; + + return node; +} + +/* Scans all of the characters in the current locale for their properties. */ +Py_LOCAL_INLINE(void) scan_locale_chars(RE_LocaleInfo* locale_info) { + int c; + + for (c = 0; c < 0x100; c++) { + unsigned short props = 0; + + if (isalnum(c)) + props |= RE_LOCALE_ALNUM; + if (isalpha(c)) + props |= RE_LOCALE_ALPHA; + if (iscntrl(c)) + props |= RE_LOCALE_CNTRL; + if (isdigit(c)) + props |= RE_LOCALE_DIGIT; + if (isgraph(c)) + props |= RE_LOCALE_GRAPH; + if (islower(c)) + props |= RE_LOCALE_LOWER; + if (isprint(c)) + props |= RE_LOCALE_PRINT; + if (ispunct(c)) + props |= RE_LOCALE_PUNCT; + if (isspace(c)) + props |= RE_LOCALE_SPACE; + if (isupper(c)) + props |= RE_LOCALE_UPPER; + + locale_info->properties[c] = props; + locale_info->uppercase[c] = (unsigned char)toupper(c); + locale_info->lowercase[c] = (unsigned char)tolower(c); + } +} + +/* Compiles regular expression code to a PatternObject. + * + * The regular expression code is provided as a list and is then compiled to + * 'nodes'. Various details about the regular expression are discovered during + * compilation and stored in the PatternObject. + */ +static PyObject* re_compile(PyObject* self_, PyObject* args) { + PyObject* pattern; + Py_ssize_t flags = 0; + PyObject* code_list; + PyObject* groupindex; + PyObject* indexgroup; + PyObject* named_lists; + PyObject* named_list_indexes; + Py_ssize_t req_offset; + PyObject* required_chars; + Py_ssize_t req_flags; + size_t public_group_count; + BOOL unpacked; + Py_ssize_t code_len; + RE_CODE* code; + Py_ssize_t i; + RE_CODE* req_chars; + size_t req_length; + PyObject* packed_code_list; + PatternObject* self; + BOOL unicode; + BOOL locale; + BOOL ascii; + BOOL ok; + + if (!PyArg_ParseTuple(args, "OnOOOOOnOnn:re_compile", &pattern, &flags, + &code_list, &groupindex, &indexgroup, &named_lists, &named_list_indexes, + &req_offset, &required_chars, &req_flags, &public_group_count)) + return NULL; + + /* If it came from a pickled source, code_list will be a packed code list + * in a bytestring. + */ + if (PyBytes_Check(code_list)) { + packed_code_list = code_list; + code_list = unpack_code_list(packed_code_list); + if (!code_list) + return NULL; + + unpacked = TRUE; + } else + unpacked = FALSE; + + /* Read the regex code. */ + code_len = PyList_Size(code_list); + code = (RE_CODE*)re_alloc((size_t)code_len * sizeof(RE_CODE)); + if (!code) { + if (unpacked) { + /* code_list has been built from a packed code list. */ + Py_DECREF(code_list); + } + return NULL; + } + + for (i = 0; i < code_len; i++) { + PyObject* o; + size_t value; + + /* PyList_GetItem borrows a reference. */ + o = PyList_GetItem(code_list, i); + + value = PyLong_AsUnsignedLong(o); + if ((Py_ssize_t)value == -1 && PyErr_Occurred()) + goto error; + + code[i] = (RE_CODE)value; + if (code[i] != value) + goto error; + } + + /* Get the required characters. */ + get_required_chars(required_chars, &req_chars, &req_length); + + if (!unpacked) { + /* Pack the code list in case it's needed for pickling. */ + packed_code_list = pack_code_list(code, code_len); + if (!packed_code_list) { + set_error(RE_ERROR_MEMORY, NULL); + re_dealloc(req_chars); + re_dealloc(code); + return NULL; + } + } + + /* Create the PatternObject. */ + self = PyObject_NEW(PatternObject, &Pattern_Type); + if (!self) { + set_error(RE_ERROR_MEMORY, NULL); + if (unpacked) { + Py_DECREF(code_list); + } else { + Py_DECREF(packed_code_list); + } + + re_dealloc(req_chars); + re_dealloc(code); + return NULL; + } + + /* Initialise the PatternObject. */ + self->pattern = pattern; + self->flags = flags; + self->packed_code_list = packed_code_list; + self->weakreflist = NULL; + self->start_node = NULL; + self->repeat_count = 0; + self->true_group_count = 0; + self->public_group_count = public_group_count; + self->visible_capture_count = 0; + self->group_end_index = 0; + self->groupindex = groupindex; + self->indexgroup = indexgroup; + self->named_lists = named_lists; + self->named_lists_count = (size_t)PyDict_Size(named_lists); + self->partial_named_lists[0] = NULL; + self->partial_named_lists[1] = NULL; + self->named_list_indexes = named_list_indexes; + self->node_capacity = 0; + self->node_count = 0; + self->node_list = NULL; + self->group_info_capacity = 0; + self->group_info = NULL; + self->call_ref_info_capacity = 0; + self->call_ref_info_count = 0; + self->call_ref_info = NULL; + self->repeat_info_capacity = 0; + self->repeat_info = NULL; + self->groups_storage = NULL; + self->repeats_storage = NULL; + self->stack_storage = NULL; + self->stack_capacity = 0; + self->fuzzy_count = 0; + self->req_offset = req_offset; + self->required_chars = required_chars; + self->req_flags = req_flags; + self->req_string = NULL; + self->locale_info = NULL; + Py_INCREF(self->pattern); + if (unpacked) { + Py_INCREF(self->packed_code_list); + } + Py_INCREF(self->groupindex); + Py_INCREF(self->indexgroup); + Py_INCREF(self->named_lists); + Py_INCREF(self->named_list_indexes); + Py_INCREF(self->required_chars); + + /* Initialise the character encoding. */ + unicode = (flags & RE_FLAG_UNICODE) != 0; + locale = (flags & RE_FLAG_LOCALE) != 0; + ascii = (flags & RE_FLAG_ASCII) != 0; + if (!unicode && !locale && !ascii) { + if (PyBytes_Check(self->pattern)) + ascii = RE_FLAG_ASCII; + else + unicode = RE_FLAG_UNICODE; + } + if (unicode) + self->encoding = &unicode_encoding; + else if (locale) + self->encoding = &locale_encoding; + else if (ascii) + self->encoding = &ascii_encoding; + + /* Compile the regular expression code to nodes. */ + ok = compile_to_nodes(code, code + code_len, self); + + /* We no longer need the regular expression code. */ + re_dealloc(code); + + if (!ok) { + Py_DECREF(self); + re_dealloc(req_chars); + if (unpacked) { + Py_DECREF(code_list); + } + return NULL; + } + + /* Make a node for the required string, if there's one. */ + if (req_chars) { + /* Remove the FULLCASE flag if it's not a Unicode pattern or not + * ignoring case. + */ + if (!(self->flags & RE_FLAG_UNICODE) || !(self->flags & + RE_FLAG_IGNORECASE)) + req_flags &= ~RE_FLAG_FULLCASE; + + if (self->flags & RE_FLAG_REVERSE) { + switch (req_flags) { + case 0: + self->req_string = make_STRING_node(self, RE_OP_STRING_REV, + req_length, req_chars); + break; + case RE_FLAG_IGNORECASE | RE_FLAG_FULLCASE: + self->req_string = make_STRING_node(self, RE_OP_STRING_FLD_REV, + req_length, req_chars); + break; + case RE_FLAG_IGNORECASE: + self->req_string = make_STRING_node(self, RE_OP_STRING_IGN_REV, + req_length, req_chars); + break; + } + } else { + switch (req_flags) { + case 0: + self->req_string = make_STRING_node(self, RE_OP_STRING, + req_length, req_chars); + break; + case RE_FLAG_IGNORECASE | RE_FLAG_FULLCASE: + self->req_string = make_STRING_node(self, RE_OP_STRING_FLD, + req_length, req_chars); + break; + case RE_FLAG_IGNORECASE: + self->req_string = make_STRING_node(self, RE_OP_STRING_IGN, + req_length, req_chars); + break; + } + } + + re_dealloc(req_chars); + } + + if (locale) { + /* Store info about the characters in the locale for locale-sensitive + * matching. + */ + self->locale_info = re_alloc(sizeof(RE_LocaleInfo)); + if (!self->locale_info) { + Py_DECREF(self); + if (unpacked) { + Py_DECREF(code_list); + } + return NULL; + } + + scan_locale_chars(self->locale_info); + } + + if (unpacked) { + Py_DECREF(code_list); + } + + return (PyObject*)self; + +error: + re_dealloc(code); + set_error(RE_ERROR_ILLEGAL, NULL); + if (unpacked) { + Py_DECREF(code_list); + } + return NULL; +} + +/* Gets the size of the codewords. */ +static PyObject* get_code_size(PyObject* self, PyObject* unused) { + return Py_BuildValue("n", sizeof(RE_CODE)); +} + +/* Gets the property dict. */ +static PyObject* get_properties(PyObject* self_, PyObject* args) { + Py_INCREF(property_dict); + + return property_dict; +} + +/* Folds the case of a string. */ +static PyObject* fold_case(PyObject* self_, PyObject* args) { + RE_StringInfo str_info; + Py_UCS4 (*char_at)(void* text, Py_ssize_t pos); + RE_EncodingTable* encoding; + RE_LocaleInfo locale_info; + Py_ssize_t folded_charsize; + void (*set_char_at)(void* text, Py_ssize_t pos, Py_UCS4 ch); + Py_ssize_t buf_size; + void* folded; + Py_ssize_t folded_len; + PyObject* result; + + Py_ssize_t flags; + PyObject* string; + if (!PyArg_ParseTuple(args, "nO:fold_case", &flags, &string)) + return NULL; + + if (!(flags & RE_FLAG_IGNORECASE)) { + Py_INCREF(string); + return string; + } + + /* Get the string. */ + if (!get_string(string, &str_info)) + return NULL; + + /* Get the function for reading from the original string. */ + switch (str_info.charsize) { + case 1: + char_at = bytes1_char_at; + break; + case 2: + char_at = bytes2_char_at; + break; + case 4: + char_at = bytes4_char_at; + break; + default: + release_buffer(&str_info); + return NULL; + } + + /* What's the encoding? */ + if (flags & RE_FLAG_UNICODE) + encoding = &unicode_encoding; + else if (flags & RE_FLAG_LOCALE) { + encoding = &locale_encoding; + scan_locale_chars(&locale_info); + } else if (flags & RE_FLAG_ASCII) + encoding = &ascii_encoding; + else + encoding = &unicode_encoding; + + /* Initially assume that the folded string will have the same width as the + * original string (usually true). + */ + folded_charsize = str_info.charsize; + + /* When folding a Unicode string, some codepoints in the range U+00..U+FF + * are mapped to codepoints in the range U+0100..U+FFFF. + */ + if (encoding == &unicode_encoding && str_info.charsize == 1) + folded_charsize = 2; + + /* Get the function for writing to the folded string. */ + switch (folded_charsize) { + case 1: + set_char_at = bytes1_set_char_at; + break; + case 2: + set_char_at = bytes2_set_char_at; + break; + case 4: + set_char_at = bytes4_set_char_at; + break; + default: + release_buffer(&str_info); + return NULL; + } + + /* Allocate a buffer for the folded string. */ + if (flags & RE_FLAG_FULLCASE) + /* When using full case-folding with Unicode, some single codepoints + * are mapped to multiple codepoints. + */ + buf_size = str_info.length * RE_MAX_FOLDED; + else + buf_size = str_info.length; + + folded = re_alloc((size_t)(buf_size * folded_charsize)); + if (!folded) { + release_buffer(&str_info); + return NULL; + } + + /* Fold the case of the string. */ + folded_len = 0; + + if (flags & RE_FLAG_FULLCASE) { + /* Full case-folding. */ + int (*full_case_fold)(RE_LocaleInfo* locale_info, Py_UCS4 ch, Py_UCS4* + folded); + Py_ssize_t i; + Py_UCS4 codepoints[RE_MAX_FOLDED]; + + full_case_fold = encoding->full_case_fold; + + for (i = 0; i < str_info.length; i++) { + int count; + int j; + + count = full_case_fold(&locale_info, char_at(str_info.characters, + i), codepoints); + for (j = 0; j < count; j++) + set_char_at(folded, folded_len + j, codepoints[j]); + + folded_len += count; + } + } else { + /* Simple case-folding. */ + Py_UCS4 (*simple_case_fold)(RE_LocaleInfo* locale_info, Py_UCS4 ch); + Py_ssize_t i; + + simple_case_fold = encoding->simple_case_fold; + + for (i = 0; i < str_info.length; i++) { + Py_UCS4 ch; + + ch = simple_case_fold(&locale_info, char_at(str_info.characters, + i)); + set_char_at(folded, i, ch); + } + + folded_len = str_info.length; + } + + /* Build the result string. */ + if (str_info.is_unicode) + result = build_unicode_value(folded, 0, folded_len, folded_charsize); + else + result = build_bytes_value(folded, 0, folded_len, folded_charsize); + + re_dealloc(folded); + + /* Release the original string's buffer. */ + release_buffer(&str_info); + + return result; +} + +/* Returns a tuple of the Unicode characters that expand on full case-folding. + */ +static PyObject* get_expand_on_folding(PyObject* self, PyObject* unused) { + int count; + PyObject* result; + int i; + + /* How many characters are there? */ + count = sizeof(re_expand_on_folding) / sizeof(re_expand_on_folding[0]); + + /* Put all the characters in a tuple. */ + result = PyTuple_New(count); + if (!result) + return NULL; + + for (i = 0; i < count; i++) { + Py_UCS4 codepoint; + PyObject* item; + + codepoint = re_expand_on_folding[i]; + + item = build_unicode_value(&codepoint, 0, 1, sizeof(codepoint)); + if (!item) + goto error; + + /* PyTuple_SetItem borrows the reference. */ + PyTuple_SetItem(result, i, item); + } + + return result; + +error: + Py_DECREF(result); + return NULL; +} + +/* Returns whether a character has a given value for a Unicode property. */ +static PyObject* has_property_value(PyObject* self_, PyObject* args) { + BOOL v; + + Py_ssize_t property_value; + Py_ssize_t character; + if (!PyArg_ParseTuple(args, "nn:has_property_value", &property_value, + &character)) + return NULL; + + v = unicode_has_property((RE_CODE)property_value, (Py_UCS4)character) ? 1 : + 0; + + return Py_BuildValue("n", v); +} + +/* Returns a list of all the simple cases of a character. + * + * If full case-folding is turned on and the character also expands on full + * case-folding, a None is appended to the list. + */ +static PyObject* get_all_cases(PyObject* self_, PyObject* args) { + RE_EncodingTable* encoding; + RE_LocaleInfo locale_info; + int count; + Py_UCS4 cases[RE_MAX_CASES]; + PyObject* result; + int i; + Py_UCS4 folded[RE_MAX_FOLDED]; + + Py_ssize_t flags; + Py_ssize_t character; + if (!PyArg_ParseTuple(args, "nn:get_all_cases", &flags, &character)) + return NULL; + + /* What's the encoding? */ + if (flags & RE_FLAG_UNICODE) + encoding = &unicode_encoding; + else if (flags & RE_FLAG_LOCALE) { + encoding = &locale_encoding; + scan_locale_chars(&locale_info); + } else if (flags & RE_FLAG_ASCII) + encoding = &ascii_encoding; + else + encoding = &unicode_encoding; + + /* Get all the simple cases. */ + count = encoding->all_cases(&locale_info, (Py_UCS4)character, cases); + + result = PyList_New(count); + if (!result) + return NULL; + + for (i = 0; i < count; i++) { + PyObject* item; + + item = Py_BuildValue("n", cases[i]); + if (!item) + goto error; + + /* PyList_SetItem borrows the reference. */ + PyList_SetItem(result, i, item); + } + + /* If the character also expands on full case-folding, append a None. */ + if ((flags & RE_FULL_CASE_FOLDING) == RE_FULL_CASE_FOLDING) { + count = encoding->full_case_fold(&locale_info, (Py_UCS4)character, + folded); + if (count > 1) + PyList_Append(result, Py_None); + } + + return result; + +error: + Py_DECREF(result); + return NULL; +} + +/* The table of the module's functions. */ +static PyMethodDef _functions[] = { + {"compile", (PyCFunction)re_compile, METH_VARARGS}, + {"get_code_size", (PyCFunction)get_code_size, METH_NOARGS}, + {"get_properties", (PyCFunction)get_properties, METH_VARARGS}, + {"fold_case", (PyCFunction)fold_case, METH_VARARGS}, + {"get_expand_on_folding", (PyCFunction)get_expand_on_folding, METH_NOARGS}, + {"has_property_value", (PyCFunction)has_property_value, METH_VARARGS}, + {"get_all_cases", (PyCFunction)get_all_cases, METH_VARARGS}, + {NULL, NULL} +}; + +/* Munges the name of a property or value. */ +void munge_name(char* name, char* munged) { + if (*name == '-') + *munged++ = *name++; + + while (*name) { + if (*name == ' ' || *name == '_' || *name == '-') + ++name; + else + *munged++ = toupper(*name++); + } + + *munged = '\0'; +} + +/* Initialises the property dictionary. */ +Py_LOCAL_INLINE(BOOL) init_property_dict(void) { + size_t value_set_count; + size_t i; + PyObject** value_dicts; + char munged[256]; + + property_dict = NULL; + + /* How many value sets are there? */ + value_set_count = 0; + + for (i = 0; i < sizeof(re_property_values) / sizeof(re_property_values[0]); + i++) { + RE_PropertyValue* value; + + value = &re_property_values[i]; + if (value->value_set >= value_set_count) + value_set_count = (size_t)value->value_set + 1; + } + + /* Quick references for the value sets. */ + value_dicts = (PyObject**)re_alloc(value_set_count * + sizeof(value_dicts[0])); + if (!value_dicts) + return FALSE; + + memset(value_dicts, 0, value_set_count * sizeof(value_dicts[0])); + + /* Build the property values dictionaries. */ + for (i = 0; i < sizeof(re_property_values) / sizeof(re_property_values[0]); + i++) { + RE_PropertyValue* value; + PyObject* v; + int status; + + value = &re_property_values[i]; + if (!value_dicts[value->value_set]) { + value_dicts[value->value_set] = PyDict_New(); + if (!value_dicts[value->value_set]) + goto error; + } + + v = Py_BuildValue("i", (int)value->id); + if (!v) + goto error; + + munge_name(re_strings[value->name], munged); + status = PyDict_SetItemString(value_dicts[value->value_set], + munged, v); + Py_DECREF(v); + if (status < 0) + goto error; + } + + /* Build the property dictionary. */ + property_dict = PyDict_New(); + if (!property_dict) + goto error; + + for (i = 0; i < sizeof(re_properties) / sizeof(re_properties[0]); i++) { + RE_Property* property; + PyObject* v; + int status; + + property = &re_properties[i]; + v = Py_BuildValue("iO", (int)property->id, + value_dicts[property->value_set]); + if (!v) + goto error; + + munge_name(re_strings[property->name], munged); + status = PyDict_SetItemString(property_dict, + munged, v); + Py_DECREF(v); + if (status < 0) + goto error; + } + + /* DECREF the value sets. Any unused ones will be deallocated. */ + for (i = 0; i < value_set_count; i++) + Py_XDECREF(value_dicts[i]); + + re_dealloc(value_dicts); + + return TRUE; + +error: + Py_XDECREF(property_dict); + + /* DECREF the value sets. */ + for (i = 0; i < value_set_count; i++) + Py_XDECREF(value_dicts[i]); + + re_dealloc(value_dicts); + + return FALSE; +} + +/* The module definition. */ +static struct PyModuleDef regex_module = { + PyModuleDef_HEAD_INIT, + "_regex", + NULL, + -1, + _functions, + NULL, + NULL, + NULL, + NULL +}; + +/* Initialises the module. */ +PyMODINIT_FUNC PyInit__regex(void) { + PyObject* m; + PyObject* d; + PyObject* x; + +#if defined(VERBOSE) + /* Unbuffered in case it crashes! */ + setvbuf(stdout, NULL, _IONBF, 0); + +#endif + /* Initialise Pattern_Type. */ + Pattern_Type.tp_dealloc = pattern_dealloc; + Pattern_Type.tp_repr = pattern_repr; + Pattern_Type.tp_flags = Py_TPFLAGS_DEFAULT; + Pattern_Type.tp_doc = pattern_doc; + Pattern_Type.tp_weaklistoffset = offsetof(PatternObject, weakreflist); + Pattern_Type.tp_methods = pattern_methods; + Pattern_Type.tp_members = pattern_members; + Pattern_Type.tp_getset = pattern_getset; + + /* Initialise Match_Type. */ + Match_Type.tp_dealloc = match_dealloc; + Match_Type.tp_repr = match_repr; + Match_Type.tp_as_mapping = &match_as_mapping; + Match_Type.tp_flags = Py_TPFLAGS_DEFAULT; + Match_Type.tp_doc = match_doc; + Match_Type.tp_methods = match_methods; + Match_Type.tp_members = match_members; + Match_Type.tp_getset = match_getset; + + /* Initialise Scanner_Type. */ + Scanner_Type.tp_dealloc = scanner_dealloc; + Scanner_Type.tp_flags = Py_TPFLAGS_DEFAULT; + Scanner_Type.tp_doc = scanner_doc; + Scanner_Type.tp_iter = scanner_iter; + Scanner_Type.tp_iternext = scanner_iternext; + Scanner_Type.tp_methods = scanner_methods; + Scanner_Type.tp_members = scanner_members; + + /* Initialise Splitter_Type. */ + Splitter_Type.tp_dealloc = splitter_dealloc; + Splitter_Type.tp_flags = Py_TPFLAGS_DEFAULT; + Splitter_Type.tp_doc = splitter_doc; + Splitter_Type.tp_iter = splitter_iter; + Splitter_Type.tp_iternext = splitter_iternext; + Splitter_Type.tp_methods = splitter_methods; + Splitter_Type.tp_members = splitter_members; + + /* Initialise Capture_Type. */ + Capture_Type.tp_dealloc = capture_dealloc; + Capture_Type.tp_str = capture_str; + Capture_Type.tp_as_mapping = &capture_as_mapping; + Capture_Type.tp_flags = Py_TPFLAGS_DEFAULT; + Capture_Type.tp_methods = capture_methods; + + /* Initialize object types */ + if (PyType_Ready(&Pattern_Type) < 0) + return NULL; + if (PyType_Ready(&Match_Type) < 0) + return NULL; + if (PyType_Ready(&Scanner_Type) < 0) + return NULL; + if (PyType_Ready(&Splitter_Type) < 0) + return NULL; + if (PyType_Ready(&Capture_Type) < 0) + return NULL; + + error_exception = NULL; + + m = PyModule_Create(®ex_module); + if (!m) + return NULL; + + d = PyModule_GetDict(m); + + x = PyLong_FromLong(RE_MAGIC); + if (x) { + PyDict_SetItemString(d, "MAGIC", x); + Py_DECREF(x); + } + + x = PyLong_FromLong(sizeof(RE_CODE)); + if (x) { + PyDict_SetItemString(d, "CODE_SIZE", x); + Py_DECREF(x); + } + + x = PyUnicode_FromString(copyright); + if (x) { + PyDict_SetItemString(d, "copyright", x); + Py_DECREF(x); + } + + /* Initialise the property dictionary. */ + if (!init_property_dict()) { + Py_DECREF(m); + return NULL; + } + + return m; +} \ No newline at end of file diff --git a/third_party/mrabarnett/_regex.h b/third_party/mrabarnett/_regex.h new file mode 100644 index 000000000..8c5e629e4 --- /dev/null +++ b/third_party/mrabarnett/_regex.h @@ -0,0 +1,237 @@ +/* + * Secret Labs' Regular Expression Engine + * + * regular expression matching engine + * + * Copyright (c) 1997-2001 by Secret Labs AB. All rights reserved. + * + * NOTE: This file is generated by regex.py. If you need + * to change anything in here, edit regex.py and run it. + * + * 2010-01-16 mrab Re-written + */ + +/* Supports Unicode version 12.1.0. */ + +#define RE_MAGIC 20100116 + +#include "_regex_unicode.h" + +/* Operators. */ +#define RE_OP_FAILURE 0 +#define RE_OP_SUCCESS 1 +#define RE_OP_ANY 2 +#define RE_OP_ANY_ALL 3 +#define RE_OP_ANY_ALL_REV 4 +#define RE_OP_ANY_REV 5 +#define RE_OP_ANY_U 6 +#define RE_OP_ANY_U_REV 7 +#define RE_OP_ATOMIC 8 +#define RE_OP_BOUNDARY 9 +#define RE_OP_BRANCH 10 +#define RE_OP_CALL_REF 11 +#define RE_OP_CHARACTER 12 +#define RE_OP_CHARACTER_IGN 13 +#define RE_OP_CHARACTER_IGN_REV 14 +#define RE_OP_CHARACTER_REV 15 +#define RE_OP_CONDITIONAL 16 +#define RE_OP_DEFAULT_BOUNDARY 17 +#define RE_OP_DEFAULT_END_OF_WORD 18 +#define RE_OP_DEFAULT_START_OF_WORD 19 +#define RE_OP_END 20 +#define RE_OP_END_OF_LINE 21 +#define RE_OP_END_OF_LINE_U 22 +#define RE_OP_END_OF_STRING 23 +#define RE_OP_END_OF_STRING_LINE 24 +#define RE_OP_END_OF_STRING_LINE_U 25 +#define RE_OP_END_OF_WORD 26 +#define RE_OP_FUZZY 27 +#define RE_OP_GRAPHEME_BOUNDARY 28 +#define RE_OP_GREEDY_REPEAT 29 +#define RE_OP_GROUP 30 +#define RE_OP_GROUP_CALL 31 +#define RE_OP_GROUP_EXISTS 32 +#define RE_OP_KEEP 33 +#define RE_OP_LAZY_REPEAT 34 +#define RE_OP_LOOKAROUND 35 +#define RE_OP_NEXT 36 +#define RE_OP_PROPERTY 37 +#define RE_OP_PROPERTY_IGN 38 +#define RE_OP_PROPERTY_IGN_REV 39 +#define RE_OP_PROPERTY_REV 40 +#define RE_OP_PRUNE 41 +#define RE_OP_RANGE 42 +#define RE_OP_RANGE_IGN 43 +#define RE_OP_RANGE_IGN_REV 44 +#define RE_OP_RANGE_REV 45 +#define RE_OP_REF_GROUP 46 +#define RE_OP_REF_GROUP_FLD 47 +#define RE_OP_REF_GROUP_FLD_REV 48 +#define RE_OP_REF_GROUP_IGN 49 +#define RE_OP_REF_GROUP_IGN_REV 50 +#define RE_OP_REF_GROUP_REV 51 +#define RE_OP_SEARCH_ANCHOR 52 +#define RE_OP_SET_DIFF 53 +#define RE_OP_SET_DIFF_IGN 54 +#define RE_OP_SET_DIFF_IGN_REV 55 +#define RE_OP_SET_DIFF_REV 56 +#define RE_OP_SET_INTER 57 +#define RE_OP_SET_INTER_IGN 58 +#define RE_OP_SET_INTER_IGN_REV 59 +#define RE_OP_SET_INTER_REV 60 +#define RE_OP_SET_SYM_DIFF 61 +#define RE_OP_SET_SYM_DIFF_IGN 62 +#define RE_OP_SET_SYM_DIFF_IGN_REV 63 +#define RE_OP_SET_SYM_DIFF_REV 64 +#define RE_OP_SET_UNION 65 +#define RE_OP_SET_UNION_IGN 66 +#define RE_OP_SET_UNION_IGN_REV 67 +#define RE_OP_SET_UNION_REV 68 +#define RE_OP_SKIP 69 +#define RE_OP_START_OF_LINE 70 +#define RE_OP_START_OF_LINE_U 71 +#define RE_OP_START_OF_STRING 72 +#define RE_OP_START_OF_WORD 73 +#define RE_OP_STRING 74 +#define RE_OP_STRING_FLD 75 +#define RE_OP_STRING_FLD_REV 76 +#define RE_OP_STRING_IGN 77 +#define RE_OP_STRING_IGN_REV 78 +#define RE_OP_STRING_REV 79 +#define RE_OP_FUZZY_EXT 80 +#define RE_OP_BODY_END 81 +#define RE_OP_BODY_START 82 +#define RE_OP_END_ATOMIC 83 +#define RE_OP_END_CONDITIONAL 84 +#define RE_OP_END_FUZZY 85 +#define RE_OP_END_GREEDY_REPEAT 86 +#define RE_OP_END_GROUP 87 +#define RE_OP_END_LAZY_REPEAT 88 +#define RE_OP_END_LOOKAROUND 89 +#define RE_OP_FUZZY_INSERT 90 +#define RE_OP_GREEDY_REPEAT_ONE 91 +#define RE_OP_GROUP_RETURN 92 +#define RE_OP_LAZY_REPEAT_ONE 93 +#define RE_OP_MATCH_BODY 94 +#define RE_OP_MATCH_TAIL 95 +#define RE_OP_START_GROUP 96 +#define RE_OP_TAIL_START 97 + +char* re_op_text[] = { + "RE_OP_FAILURE", + "RE_OP_SUCCESS", + "RE_OP_ANY", + "RE_OP_ANY_ALL", + "RE_OP_ANY_ALL_REV", + "RE_OP_ANY_REV", + "RE_OP_ANY_U", + "RE_OP_ANY_U_REV", + "RE_OP_ATOMIC", + "RE_OP_BOUNDARY", + "RE_OP_BRANCH", + "RE_OP_CALL_REF", + "RE_OP_CHARACTER", + "RE_OP_CHARACTER_IGN", + "RE_OP_CHARACTER_IGN_REV", + "RE_OP_CHARACTER_REV", + "RE_OP_CONDITIONAL", + "RE_OP_DEFAULT_BOUNDARY", + "RE_OP_DEFAULT_END_OF_WORD", + "RE_OP_DEFAULT_START_OF_WORD", + "RE_OP_END", + "RE_OP_END_OF_LINE", + "RE_OP_END_OF_LINE_U", + "RE_OP_END_OF_STRING", + "RE_OP_END_OF_STRING_LINE", + "RE_OP_END_OF_STRING_LINE_U", + "RE_OP_END_OF_WORD", + "RE_OP_FUZZY", + "RE_OP_GRAPHEME_BOUNDARY", + "RE_OP_GREEDY_REPEAT", + "RE_OP_GROUP", + "RE_OP_GROUP_CALL", + "RE_OP_GROUP_EXISTS", + "RE_OP_KEEP", + "RE_OP_LAZY_REPEAT", + "RE_OP_LOOKAROUND", + "RE_OP_NEXT", + "RE_OP_PROPERTY", + "RE_OP_PROPERTY_IGN", + "RE_OP_PROPERTY_IGN_REV", + "RE_OP_PROPERTY_REV", + "RE_OP_PRUNE", + "RE_OP_RANGE", + "RE_OP_RANGE_IGN", + "RE_OP_RANGE_IGN_REV", + "RE_OP_RANGE_REV", + "RE_OP_REF_GROUP", + "RE_OP_REF_GROUP_FLD", + "RE_OP_REF_GROUP_FLD_REV", + "RE_OP_REF_GROUP_IGN", + "RE_OP_REF_GROUP_IGN_REV", + "RE_OP_REF_GROUP_REV", + "RE_OP_SEARCH_ANCHOR", + "RE_OP_SET_DIFF", + "RE_OP_SET_DIFF_IGN", + "RE_OP_SET_DIFF_IGN_REV", + "RE_OP_SET_DIFF_REV", + "RE_OP_SET_INTER", + "RE_OP_SET_INTER_IGN", + "RE_OP_SET_INTER_IGN_REV", + "RE_OP_SET_INTER_REV", + "RE_OP_SET_SYM_DIFF", + "RE_OP_SET_SYM_DIFF_IGN", + "RE_OP_SET_SYM_DIFF_IGN_REV", + "RE_OP_SET_SYM_DIFF_REV", + "RE_OP_SET_UNION", + "RE_OP_SET_UNION_IGN", + "RE_OP_SET_UNION_IGN_REV", + "RE_OP_SET_UNION_REV", + "RE_OP_SKIP", + "RE_OP_START_OF_LINE", + "RE_OP_START_OF_LINE_U", + "RE_OP_START_OF_STRING", + "RE_OP_START_OF_WORD", + "RE_OP_STRING", + "RE_OP_STRING_FLD", + "RE_OP_STRING_FLD_REV", + "RE_OP_STRING_IGN", + "RE_OP_STRING_IGN_REV", + "RE_OP_STRING_REV", + "RE_OP_FUZZY_EXT", + "RE_OP_BODY_END", + "RE_OP_BODY_START", + "RE_OP_END_ATOMIC", + "RE_OP_END_CONDITIONAL", + "RE_OP_END_FUZZY", + "RE_OP_END_GREEDY_REPEAT", + "RE_OP_END_GROUP", + "RE_OP_END_LAZY_REPEAT", + "RE_OP_END_LOOKAROUND", + "RE_OP_FUZZY_INSERT", + "RE_OP_GREEDY_REPEAT_ONE", + "RE_OP_GROUP_RETURN", + "RE_OP_LAZY_REPEAT_ONE", + "RE_OP_MATCH_BODY", + "RE_OP_MATCH_TAIL", + "RE_OP_START_GROUP", + "RE_OP_TAIL_START" +}; + +#define RE_FLAG_ASCII 0x80 +#define RE_FLAG_BESTMATCH 0x1000 +#define RE_FLAG_DEBUG 0x200 +#define RE_FLAG_DOTALL 0x10 +#define RE_FLAG_ENHANCEMATCH 0x8000 +#define RE_FLAG_FULLCASE 0x4000 +#define RE_FLAG_IGNORECASE 0x2 +#define RE_FLAG_LOCALE 0x4 +#define RE_FLAG_MULTILINE 0x8 +#define RE_FLAG_POSIX 0x10000 +#define RE_FLAG_REVERSE 0x400 +#define RE_FLAG_TEMPLATE 0x1 +#define RE_FLAG_UNICODE 0x20 +#define RE_FLAG_VERBOSE 0x40 +#define RE_FLAG_VERSION0 0x2000 +#define RE_FLAG_VERSION1 0x100 +#define RE_FLAG_WORD 0x800 \ No newline at end of file diff --git a/third_party/mrabarnett/_regex_unicode.c b/third_party/mrabarnett/_regex_unicode.c new file mode 100644 index 000000000..7196dbdea --- /dev/null +++ b/third_party/mrabarnett/_regex_unicode.c @@ -0,0 +1,31399 @@ +/* For Unicode version 16.0.0 */ + +#include "_regex_unicode.h" + +#define RE_BLANK_MASK ((1 << RE_PROP_ZL) | (1 << RE_PROP_ZP)) +#define RE_GRAPH_MASK ((1 << RE_PROP_CC) | (1 << RE_PROP_CS) | (1 << RE_PROP_CN)) +#define RE_WORD_MASK (RE_PROP_M_MASK | (1 << RE_PROP_ND) | (1 << RE_PROP_PC)) + +typedef struct { + RE_UINT8 scripts[RE_MAX_SCX]; +} RE_ScriptExt; + +typedef struct { + RE_UINT32 delta; + RE_UINT16 others[RE_MAX_CASES - 1]; +} RE_AllCases; + +typedef struct { + RE_UINT16 data[RE_MAX_FOLDED]; +} RE_FullCaseFolding; + +/* Strings. */ +char* re_strings[] = { + "-1/2", + "0", + "1", + "1/10", + "1/12", + "1/16", + "1/160", + "1/2", + "1/20", + "1/3", + "1/32", + "1/320", + "1/4", + "1/40", + "1/5", + "1/6", + "1/64", + "1/7", + "1/8", + "1/80", + "1/9", + "10", + "100", + "1000", + "10000", + "100000", + "1000000", + "10000000", + "100000000", + "1000000000", + "10000000000", + "1000000000000", + "10000000000000000", + "103", + "107", + "11", + "11/12", + "11/2", + "118", + "12", + "122", + "129", + "13", + "13/2", + "130", + "132", + "133", + "14", + "15", + "15/2", + "16", + "17", + "17/2", + "18", + "19", + "2", + "2/3", + "2/5", + "20", + "200", + "2000", + "20000", + "200000", + "20000000", + "202", + "21", + "214", + "216", + "216000", + "218", + "22", + "220", + "222", + "224", + "226", + "228", + "23", + "230", + "232", + "233", + "234", + "24", + "240", + "25", + "26", + "27", + "28", + "29", + "3", + "3/16", + "3/2", + "3/20", + "3/4", + "3/5", + "3/64", + "3/8", + "3/80", + "30", + "300", + "3000", + "30000", + "300000", + "31", + "32", + "33", + "34", + "35", + "36", + "37", + "38", + "39", + "4", + "4/5", + "40", + "400", + "4000", + "40000", + "400000", + "41", + "42", + "43", + "432000", + "44", + "45", + "46", + "47", + "48", + "49", + "5", + "5/12", + "5/2", + "5/6", + "5/8", + "50", + "500", + "5000", + "50000", + "500000", + "6", + "60", + "600", + "6000", + "60000", + "600000", + "7", + "7/12", + "7/2", + "7/8", + "70", + "700", + "7000", + "70000", + "700000", + "8", + "80", + "800", + "8000", + "80000", + "800000", + "84", + "9", + "9/2", + "90", + "900", + "9000", + "90000", + "900000", + "91", + "A", + "ABOVE", + "ABOVELEFT", + "ABOVERIGHT", + "ADLAM", + "ADLM", + "AEGEANNUMBERS", + "AFRICANFEH", + "AFRICANNOON", + "AFRICANQAF", + "AGHB", + "AHEX", + "AHOM", + "AI", + "AIN", + "AK", + "AKSARA", + "AKSARAPREBASE", + "AKSARASTART", + "AL", + "ALAPH", + "ALCHEMICAL", + "ALCHEMICALSYMBOLS", + "ALEF", + "ALETTER", + "ALNUM", + "ALPHA", + "ALPHABETIC", + "ALPHABETICPF", + "ALPHABETICPRESENTATIONFORMS", + "ALPHANUMERIC", + "AMBIGUOUS", + "AN", + "ANATOLIANHIEROGLYPHS", + "ANCIENTGREEKMUSIC", + "ANCIENTGREEKMUSICALNOTATION", + "ANCIENTGREEKNUMBERS", + "ANCIENTSYMBOLS", + "ANY", + "AP", + "AR", + "ARAB", + "ARABIC", + "ARABICEXTA", + "ARABICEXTB", + "ARABICEXTC", + "ARABICEXTENDEDA", + "ARABICEXTENDEDB", + "ARABICEXTENDEDC", + "ARABICLETTER", + "ARABICMATH", + "ARABICMATHEMATICALALPHABETICSYMBOLS", + "ARABICNUMBER", + "ARABICPFA", + "ARABICPFB", + "ARABICPRESENTATIONFORMSA", + "ARABICPRESENTATIONFORMSB", + "ARABICSUP", + "ARABICSUPPLEMENT", + "ARMENIAN", + "ARMI", + "ARMN", + "ARROWS", + "AS", + "ASCII", + "ASCIIHEXDIGIT", + "ASSIGNED", + "AT", + "ATA", + "ATAR", + "ATB", + "ATBL", + "ATERM", + "ATTACHEDABOVE", + "ATTACHEDABOVERIGHT", + "ATTACHEDBELOW", + "ATTACHEDBELOWLEFT", + "AVAGRAHA", + "AVESTAN", + "AVST", + "B", + "B2", + "BA", + "BALI", + "BALINESE", + "BAMU", + "BAMUM", + "BAMUMSUP", + "BAMUMSUPPLEMENT", + "BASICLATIN", + "BASS", + "BASSAVAH", + "BATAK", + "BATK", + "BB", + "BC", + "BEH", + "BELOW", + "BELOWLEFT", + "BELOWRIGHT", + "BENG", + "BENGALI", + "BETH", + "BHAIKSUKI", + "BHKS", + "BIDIC", + "BIDICLASS", + "BIDICONTROL", + "BIDIM", + "BIDIMIRRORED", + "BINDU", + "BK", + "BL", + "BLANK", + "BLK", + "BLOCK", + "BLOCKELEMENTS", + "BN", + "BOPO", + "BOPOMOFO", + "BOPOMOFOEXT", + "BOPOMOFOEXTENDED", + "BOTTOM", + "BOTTOMANDLEFT", + "BOTTOMANDRIGHT", + "BOUNDARYNEUTRAL", + "BOXDRAWING", + "BR", + "BRAH", + "BRAHMI", + "BRAHMIJOININGNUMBER", + "BRAI", + "BRAILLE", + "BRAILLEPATTERNS", + "BREAKAFTER", + "BREAKBEFORE", + "BREAKBOTH", + "BREAKSYMBOLS", + "BUGI", + "BUGINESE", + "BUHD", + "BUHID", + "BURUSHASKIYEHBARREE", + "BYZANTINEMUSIC", + "BYZANTINEMUSICALSYMBOLS", + "C", + "C&", + "CAKM", + "CAN", + "CANADIANABORIGINAL", + "CANADIANSYLLABICS", + "CANONICAL", + "CANONICALCOMBININGCLASS", + "CANS", + "CANTILLATIONMARK", + "CARI", + "CARIAN", + "CARRIAGERETURN", + "CASED", + "CASEDLETTER", + "CASEIGNORABLE", + "CAUCASIANALBANIAN", + "CB", + "CC", + "CCC", + "CCC10", + "CCC103", + "CCC107", + "CCC11", + "CCC118", + "CCC12", + "CCC122", + "CCC129", + "CCC13", + "CCC130", + "CCC132", + "CCC133", + "CCC14", + "CCC15", + "CCC16", + "CCC17", + "CCC18", + "CCC19", + "CCC20", + "CCC21", + "CCC22", + "CCC23", + "CCC24", + "CCC25", + "CCC26", + "CCC27", + "CCC28", + "CCC29", + "CCC30", + "CCC31", + "CCC32", + "CCC33", + "CCC34", + "CCC35", + "CCC36", + "CCC84", + "CCC91", + "CF", + "CHAKMA", + "CHAM", + "CHANGESWHENCASEFOLDED", + "CHANGESWHENCASEMAPPED", + "CHANGESWHENLOWERCASED", + "CHANGESWHENTITLECASED", + "CHANGESWHENUPPERCASED", + "CHER", + "CHEROKEE", + "CHEROKEESUP", + "CHEROKEESUPPLEMENT", + "CHESSSYMBOLS", + "CHORASMIAN", + "CHRS", + "CI", + "CIRCLE", + "CJ", + "CJK", + "CJKCOMPAT", + "CJKCOMPATFORMS", + "CJKCOMPATIBILITY", + "CJKCOMPATIBILITYFORMS", + "CJKCOMPATIBILITYIDEOGRAPHS", + "CJKCOMPATIBILITYIDEOGRAPHSSUPPLEMENT", + "CJKCOMPATIDEOGRAPHS", + "CJKCOMPATIDEOGRAPHSSUP", + "CJKEXTA", + "CJKEXTB", + "CJKEXTC", + "CJKEXTD", + "CJKEXTE", + "CJKEXTF", + "CJKEXTG", + "CJKEXTH", + "CJKEXTI", + "CJKRADICALSSUP", + "CJKRADICALSSUPPLEMENT", + "CJKSTROKES", + "CJKSYMBOLS", + "CJKSYMBOLSANDPUNCTUATION", + "CJKUNIFIEDIDEOGRAPHS", + "CJKUNIFIEDIDEOGRAPHSEXTENSIONA", + "CJKUNIFIEDIDEOGRAPHSEXTENSIONB", + "CJKUNIFIEDIDEOGRAPHSEXTENSIONC", + "CJKUNIFIEDIDEOGRAPHSEXTENSIOND", + "CJKUNIFIEDIDEOGRAPHSEXTENSIONE", + "CJKUNIFIEDIDEOGRAPHSEXTENSIONF", + "CJKUNIFIEDIDEOGRAPHSEXTENSIONG", + "CJKUNIFIEDIDEOGRAPHSEXTENSIONH", + "CJKUNIFIEDIDEOGRAPHSEXTENSIONI", + "CL", + "CLOSE", + "CLOSEPARENTHESIS", + "CLOSEPUNCTUATION", + "CM", + "CN", + "CNTRL", + "CO", + "COM", + "COMBININGDIACRITICALMARKS", + "COMBININGDIACRITICALMARKSEXTENDED", + "COMBININGDIACRITICALMARKSFORSYMBOLS", + "COMBININGDIACRITICALMARKSSUPPLEMENT", + "COMBININGHALFMARKS", + "COMBININGMARK", + "COMBININGMARKSFORSYMBOLS", + "COMMON", + "COMMONINDICNUMBERFORMS", + "COMMONSEPARATOR", + "COMPAT", + "COMPATJAMO", + "COMPLEXCONTEXT", + "CONDITIONALJAPANESESTARTER", + "CONNECTORPUNCTUATION", + "CONSONANT", + "CONSONANTDEAD", + "CONSONANTFINAL", + "CONSONANTHEADLETTER", + "CONSONANTINITIALPOSTFIXED", + "CONSONANTKILLER", + "CONSONANTMEDIAL", + "CONSONANTPLACEHOLDER", + "CONSONANTPRECEDINGREPHA", + "CONSONANTPREFIXED", + "CONSONANTSUBJOINED", + "CONSONANTSUCCEEDINGREPHA", + "CONSONANTWITHSTACKER", + "CONTINGENTBREAK", + "CONTROL", + "CONTROLPICTURES", + "COPT", + "COPTIC", + "COPTICEPACTNUMBERS", + "COUNTINGROD", + "COUNTINGRODNUMERALS", + "CP", + "CPMN", + "CPRT", + "CR", + "CS", + "CUNEIFORM", + "CUNEIFORMNUMBERS", + "CUNEIFORMNUMBERSANDPUNCTUATION", + "CURRENCYSYMBOL", + "CURRENCYSYMBOLS", + "CWCF", + "CWCM", + "CWL", + "CWT", + "CWU", + "CYPRIOT", + "CYPRIOTSYLLABARY", + "CYPROMINOAN", + "CYRILLIC", + "CYRILLICEXTA", + "CYRILLICEXTB", + "CYRILLICEXTC", + "CYRILLICEXTD", + "CYRILLICEXTENDEDA", + "CYRILLICEXTENDEDB", + "CYRILLICEXTENDEDC", + "CYRILLICEXTENDEDD", + "CYRILLICSUP", + "CYRILLICSUPPLEMENT", + "CYRILLICSUPPLEMENTARY", + "CYRL", + "D", + "DA", + "DAL", + "DALATHRISH", + "DASH", + "DASHPUNCTUATION", + "DB", + "DE", + "DECIMAL", + "DECIMALNUMBER", + "DECOMPOSITIONTYPE", + "DEFAULTIGNORABLECODEPOINT", + "DEP", + "DEPRECATED", + "DESERET", + "DEVA", + "DEVANAGARI", + "DEVANAGARIEXT", + "DEVANAGARIEXTA", + "DEVANAGARIEXTENDED", + "DEVANAGARIEXTENDEDA", + "DI", + "DIA", + "DIACRITIC", + "DIACRITICALS", + "DIACRITICALSEXT", + "DIACRITICALSFORSYMBOLS", + "DIACRITICALSSUP", + "DIAK", + "DIGIT", + "DINGBATS", + "DIVESAKURU", + "DOGR", + "DOGRA", + "DOMINO", + "DOMINOTILES", + "DOUBLEABOVE", + "DOUBLEBELOW", + "DOUBLEQUOTE", + "DQ", + "DSRT", + "DT", + "DUALJOINING", + "DUPL", + "DUPLOYAN", + "E", + "EA", + "EARLYDYNASTICCUNEIFORM", + "EASTASIANWIDTH", + "EB", + "EBASE", + "EBASEGAZ", + "EBG", + "ECOMP", + "EGYP", + "EGYPTIANHIEROGLYPHFORMATCONTROLS", + "EGYPTIANHIEROGLYPHS", + "EGYPTIANHIEROGLYPHSEXTA", + "EGYPTIANHIEROGLYPHSEXTENDEDA", + "ELBA", + "ELBASAN", + "ELYM", + "ELYMAIC", + "EM", + "EMOD", + "EMODIFIER", + "EMOJI", + "EMOJICOMPONENT", + "EMOJIMODIFIER", + "EMOJIMODIFIERBASE", + "EMOJIPRESENTATION", + "EMOTICONS", + "EN", + "ENC", + "ENCLOSEDALPHANUM", + "ENCLOSEDALPHANUMERICS", + "ENCLOSEDALPHANUMERICSUPPLEMENT", + "ENCLOSEDALPHANUMSUP", + "ENCLOSEDCJK", + "ENCLOSEDCJKLETTERSANDMONTHS", + "ENCLOSEDIDEOGRAPHICSUP", + "ENCLOSEDIDEOGRAPHICSUPPLEMENT", + "ENCLOSINGMARK", + "EPRES", + "ES", + "ET", + "ETHI", + "ETHIOPIC", + "ETHIOPICEXT", + "ETHIOPICEXTA", + "ETHIOPICEXTB", + "ETHIOPICEXTENDED", + "ETHIOPICEXTENDEDA", + "ETHIOPICEXTENDEDB", + "ETHIOPICSUP", + "ETHIOPICSUPPLEMENT", + "EUROPEANNUMBER", + "EUROPEANSEPARATOR", + "EUROPEANTERMINATOR", + "EX", + "EXCLAMATION", + "EXT", + "EXTEND", + "EXTENDEDPICTOGRAPHIC", + "EXTENDER", + "EXTENDNUMLET", + "EXTPICT", + "F", + "FALSE", + "FARSIYEH", + "FE", + "FEH", + "FIN", + "FINAL", + "FINALPUNCTUATION", + "FINALSEMKATH", + "FIRSTSTRONGISOLATE", + "FO", + "FONT", + "FORMAT", + "FRA", + "FRACTION", + "FSI", + "FULLWIDTH", + "GAF", + "GAMAL", + "GARA", + "GARAY", + "GAZ", + "GC", + "GCB", + "GEMINATIONMARK", + "GENERALCATEGORY", + "GENERALPUNCTUATION", + "GEOMETRICSHAPES", + "GEOMETRICSHAPESEXT", + "GEOMETRICSHAPESEXTENDED", + "GEOR", + "GEORGIAN", + "GEORGIANEXT", + "GEORGIANEXTENDED", + "GEORGIANSUP", + "GEORGIANSUPPLEMENT", + "GL", + "GLAG", + "GLAGOLITIC", + "GLAGOLITICSUP", + "GLAGOLITICSUPPLEMENT", + "GLUE", + "GLUEAFTERZWJ", + "GONG", + "GONM", + "GOTH", + "GOTHIC", + "GRAN", + "GRANTHA", + "GRAPH", + "GRAPHEMEBASE", + "GRAPHEMECLUSTERBREAK", + "GRAPHEMEEXTEND", + "GRAPHEMELINK", + "GRBASE", + "GREEK", + "GREEKANDCOPTIC", + "GREEKEXT", + "GREEKEXTENDED", + "GREK", + "GREXT", + "GRLINK", + "GUJARATI", + "GUJR", + "GUKH", + "GUNJALAGONDI", + "GURMUKHI", + "GURU", + "GURUNGKHEMA", + "H", + "H2", + "H3", + "HAH", + "HALFANDFULLFORMS", + "HALFMARKS", + "HALFWIDTH", + "HALFWIDTHANDFULLWIDTHFORMS", + "HAMZAONHEHGOAL", + "HAN", + "HANG", + "HANGUL", + "HANGULCOMPATIBILITYJAMO", + "HANGULJAMO", + "HANGULJAMOEXTENDEDA", + "HANGULJAMOEXTENDEDB", + "HANGULSYLLABLES", + "HANGULSYLLABLETYPE", + "HANI", + "HANIFIROHINGYA", + "HANIFIROHINGYAKINNAYA", + "HANIFIROHINGYAPA", + "HANO", + "HANR", + "HANREADING", + "HANUNOO", + "HATR", + "HATRAN", + "HE", + "HEBR", + "HEBREW", + "HEBREWLETTER", + "HEH", + "HEHGOAL", + "HETH", + "HEX", + "HEXDIGIT", + "HIGHPRIVATEUSESURROGATES", + "HIGHPUSURROGATES", + "HIGHSURROGATES", + "HIRA", + "HIRAGANA", + "HL", + "HLUW", + "HMNG", + "HMNP", + "HORIZSPACE", + "HRKT", + "HST", + "HUNG", + "HY", + "HYPHEN", + "ID", + "IDC", + "IDCOMPATMATHCONTINUE", + "IDCOMPATMATHSTART", + "IDCONTINUE", + "IDEO", + "IDEOGRAPHIC", + "IDEOGRAPHICDESCRIPTIONCHARACTERS", + "IDEOGRAPHICSYMBOLS", + "IDEOGRAPHICSYMBOLSANDPUNCTUATION", + "IDS", + "IDSB", + "IDSBINARYOPERATOR", + "IDST", + "IDSTART", + "IDSTRINARYOPERATOR", + "IDSU", + "IDSUNARYOPERATOR", + "IMPERIALARAMAIC", + "IN", + "INCB", + "INDICCONJUNCTBREAK", + "INDICNUMBERFORMS", + "INDICPOSITIONALCATEGORY", + "INDICSIYAQNUMBERS", + "INDICSYLLABICCATEGORY", + "INFIXNUMERIC", + "INHERITED", + "INIT", + "INITIAL", + "INITIALPUNCTUATION", + "INPC", + "INSC", + "INSCRIPTIONALPAHLAVI", + "INSCRIPTIONALPARTHIAN", + "INSEPARABLE", + "INSEPERABLE", + "INVISIBLESTACKER", + "IOTASUBSCRIPT", + "IPAEXT", + "IPAEXTENSIONS", + "IS", + "ISO", + "ISOLATED", + "ITAL", + "JAMO", + "JAMOEXTA", + "JAMOEXTB", + "JAVA", + "JAVANESE", + "JG", + "JL", + "JOINC", + "JOINCAUSING", + "JOINCONTROL", + "JOINER", + "JOININGGROUP", + "JOININGTYPE", + "JT", + "JV", + "KA", + "KAF", + "KAITHI", + "KAKTOVIKNUMERALS", + "KALI", + "KANA", + "KANAEXTA", + "KANAEXTB", + "KANAEXTENDEDA", + "KANAEXTENDEDB", + "KANASUP", + "KANASUPPLEMENT", + "KANAVOICING", + "KANBUN", + "KANGXI", + "KANGXIRADICALS", + "KANNADA", + "KAPH", + "KASHMIRIYEH", + "KATAKANA", + "KATAKANAEXT", + "KATAKANAORHIRAGANA", + "KATAKANAPHONETICEXTENSIONS", + "KAWI", + "KAYAHLI", + "KHAPH", + "KHAR", + "KHAROSHTHI", + "KHITANSMALLSCRIPT", + "KHMER", + "KHMERSYMBOLS", + "KHMR", + "KHOJ", + "KHOJKI", + "KHUDAWADI", + "KIRATRAI", + "KITS", + "KNDA", + "KNOTTEDHEH", + "KRAI", + "KTHI", + "KV", + "L", + "L&", + "LAM", + "LAMADH", + "LANA", + "LAO", + "LAOO", + "LATIN", + "LATIN1", + "LATIN1SUP", + "LATIN1SUPPLEMENT", + "LATINEXTA", + "LATINEXTADDITIONAL", + "LATINEXTB", + "LATINEXTC", + "LATINEXTD", + "LATINEXTE", + "LATINEXTENDEDA", + "LATINEXTENDEDADDITIONAL", + "LATINEXTENDEDB", + "LATINEXTENDEDC", + "LATINEXTENDEDD", + "LATINEXTENDEDE", + "LATINEXTENDEDF", + "LATINEXTENDEDG", + "LATINEXTF", + "LATINEXTG", + "LATN", + "LB", + "LC", + "LE", + "LEADINGJAMO", + "LEFT", + "LEFTANDRIGHT", + "LEFTJOINING", + "LEFTTORIGHT", + "LEFTTORIGHTEMBEDDING", + "LEFTTORIGHTISOLATE", + "LEFTTORIGHTOVERRIDE", + "LEPC", + "LEPCHA", + "LETTER", + "LETTERLIKESYMBOLS", + "LETTERNUMBER", + "LF", + "LIMB", + "LIMBU", + "LINA", + "LINB", + "LINEARA", + "LINEARB", + "LINEARBIDEOGRAMS", + "LINEARBSYLLABARY", + "LINEBREAK", + "LINEFEED", + "LINESEPARATOR", + "LINKER", + "LISU", + "LISUSUP", + "LISUSUPPLEMENT", + "LL", + "LM", + "LO", + "LOE", + "LOGICALORDEREXCEPTION", + "LOWER", + "LOWERCASE", + "LOWERCASELETTER", + "LOWSURROGATES", + "LRE", + "LRI", + "LRO", + "LT", + "LU", + "LV", + "LVSYLLABLE", + "LVT", + "LVTSYLLABLE", + "LYCI", + "LYCIAN", + "LYDI", + "LYDIAN", + "M", + "M&", + "MAHAJANI", + "MAHJ", + "MAHJONG", + "MAHJONGTILES", + "MAKA", + "MAKASAR", + "MALAYALAM", + "MALAYALAMBHA", + "MALAYALAMJA", + "MALAYALAMLLA", + "MALAYALAMLLLA", + "MALAYALAMNGA", + "MALAYALAMNNA", + "MALAYALAMNNNA", + "MALAYALAMNYA", + "MALAYALAMRA", + "MALAYALAMSSA", + "MALAYALAMTTA", + "MAND", + "MANDAIC", + "MANDATORYBREAK", + "MANI", + "MANICHAEAN", + "MANICHAEANALEPH", + "MANICHAEANAYIN", + "MANICHAEANBETH", + "MANICHAEANDALETH", + "MANICHAEANDHAMEDH", + "MANICHAEANFIVE", + "MANICHAEANGIMEL", + "MANICHAEANHETH", + "MANICHAEANHUNDRED", + "MANICHAEANKAPH", + "MANICHAEANLAMEDH", + "MANICHAEANMEM", + "MANICHAEANNUN", + "MANICHAEANONE", + "MANICHAEANPE", + "MANICHAEANQOPH", + "MANICHAEANRESH", + "MANICHAEANSADHE", + "MANICHAEANSAMEKH", + "MANICHAEANTAW", + "MANICHAEANTEN", + "MANICHAEANTETH", + "MANICHAEANTHAMEDH", + "MANICHAEANTWENTY", + "MANICHAEANWAW", + "MANICHAEANYODH", + "MANICHAEANZAYIN", + "MARC", + "MARCHEN", + "MARK", + "MASARAMGONDI", + "MATH", + "MATHALPHANUM", + "MATHEMATICALALPHANUMERICSYMBOLS", + "MATHEMATICALOPERATORS", + "MATHOPERATORS", + "MATHSYMBOL", + "MAYANNUMERALS", + "MAYBE", + "MB", + "MC", + "MCM", + "ME", + "MED", + "MEDEFAIDRIN", + "MEDF", + "MEDIAL", + "MEEM", + "MEETEIMAYEK", + "MEETEIMAYEKEXT", + "MEETEIMAYEKEXTENSIONS", + "MEND", + "MENDEKIKAKUI", + "MERC", + "MERO", + "MEROITICCURSIVE", + "MEROITICHIEROGLYPHS", + "MIAO", + "MIDLETTER", + "MIDNUM", + "MIDNUMLET", + "MIM", + "MISCARROWS", + "MISCELLANEOUSMATHEMATICALSYMBOLSA", + "MISCELLANEOUSMATHEMATICALSYMBOLSB", + "MISCELLANEOUSSYMBOLS", + "MISCELLANEOUSSYMBOLSANDARROWS", + "MISCELLANEOUSSYMBOLSANDPICTOGRAPHS", + "MISCELLANEOUSTECHNICAL", + "MISCMATHSYMBOLSA", + "MISCMATHSYMBOLSB", + "MISCPICTOGRAPHS", + "MISCSYMBOLS", + "MISCTECHNICAL", + "ML", + "MLYM", + "MN", + "MODI", + "MODIFIERCOMBININGMARK", + "MODIFIERLETTER", + "MODIFIERLETTERS", + "MODIFIERSYMBOL", + "MODIFIERTONELETTERS", + "MODIFYINGLETTER", + "MONG", + "MONGOLIAN", + "MONGOLIANSUP", + "MONGOLIANSUPPLEMENT", + "MRO", + "MROO", + "MTEI", + "MULT", + "MULTANI", + "MUSIC", + "MUSICALSYMBOLS", + "MYANMAR", + "MYANMAREXTA", + "MYANMAREXTB", + "MYANMAREXTC", + "MYANMAREXTENDEDA", + "MYANMAREXTENDEDB", + "MYANMAREXTENDEDC", + "MYMR", + "N", + "N&", + "NA", + "NABATAEAN", + "NAGM", + "NAGMUNDARI", + "NAN", + "NAND", + "NANDINAGARI", + "NAR", + "NARB", + "NARROW", + "NB", + "NBAT", + "NCHAR", + "ND", + "NEUTRAL", + "NEWA", + "NEWLINE", + "NEWTAILUE", + "NEXTLINE", + "NFCQC", + "NFCQUICKCHECK", + "NFDQC", + "NFDQUICKCHECK", + "NFKCQC", + "NFKCQUICKCHECK", + "NFKDQC", + "NFKDQUICKCHECK", + "NK", + "NKO", + "NKOO", + "NL", + "NO", + "NOBLOCK", + "NOBREAK", + "NOJOININGGROUP", + "NONCHARACTERCODEPOINT", + "NONE", + "NONJOINER", + "NONJOINING", + "NONSPACINGMARK", + "NONSTARTER", + "NOON", + "NOTAPPLICABLE", + "NOTREORDERED", + "NR", + "NS", + "NSHU", + "NSM", + "NT", + "NU", + "NUKTA", + "NUMBER", + "NUMBERFORMS", + "NUMBERJOINER", + "NUMERIC", + "NUMERICTYPE", + "NUMERICVALUE", + "NUN", + "NUSHU", + "NV", + "NYA", + "NYIAKENGPUACHUEHMONG", + "OALPHA", + "OCR", + "ODI", + "OGAM", + "OGHAM", + "OGREXT", + "OIDC", + "OIDS", + "OLCHIKI", + "OLCK", + "OLDHUNGARIAN", + "OLDITALIC", + "OLDNORTHARABIAN", + "OLDPERMIC", + "OLDPERSIAN", + "OLDSOGDIAN", + "OLDSOUTHARABIAN", + "OLDTURKIC", + "OLDUYGHUR", + "OLETTER", + "OLONAL", + "OLOWER", + "OMATH", + "ON", + "ONAO", + "OP", + "OPENPUNCTUATION", + "OPTICALCHARACTERRECOGNITION", + "ORIYA", + "ORKH", + "ORNAMENTALDINGBATS", + "ORYA", + "OSAGE", + "OSGE", + "OSMA", + "OSMANYA", + "OTHER", + "OTHERALPHABETIC", + "OTHERDEFAULTIGNORABLECODEPOINT", + "OTHERGRAPHEMEEXTEND", + "OTHERIDCONTINUE", + "OTHERIDSTART", + "OTHERLETTER", + "OTHERLOWERCASE", + "OTHERMATH", + "OTHERNEUTRAL", + "OTHERNUMBER", + "OTHERPUNCTUATION", + "OTHERSYMBOL", + "OTHERUPPERCASE", + "OTTOMANSIYAQNUMBERS", + "OUGR", + "OUPPER", + "OV", + "OVERLAY", + "OVERSTRUCK", + "P", + "P&", + "PAHAWHHMONG", + "PALM", + "PALMYRENE", + "PARAGRAPHSEPARATOR", + "PATSYN", + "PATTERNSYNTAX", + "PATTERNWHITESPACE", + "PATWS", + "PAUC", + "PAUCINHAU", + "PC", + "PCM", + "PD", + "PDF", + "PDI", + "PE", + "PERM", + "PF", + "PHAG", + "PHAGSPA", + "PHAISTOS", + "PHAISTOSDISC", + "PHLI", + "PHLP", + "PHNX", + "PHOENICIAN", + "PHONETICEXT", + "PHONETICEXTENSIONS", + "PHONETICEXTENSIONSSUPPLEMENT", + "PHONETICEXTSUP", + "PI", + "PLAYINGCARDS", + "PLRD", + "PO", + "POPDIRECTIONALFORMAT", + "POPDIRECTIONALISOLATE", + "POSIXALNUM", + "POSIXDIGIT", + "POSIXPUNCT", + "POSIXXDIGIT", + "POSTFIXNUMERIC", + "PP", + "PR", + "PREFIXNUMERIC", + "PREPEND", + "PREPENDEDCONCATENATIONMARK", + "PRINT", + "PRIVATEUSE", + "PRIVATEUSEAREA", + "PRTI", + "PS", + "PSALTERPAHLAVI", + "PUA", + "PUNCT", + "PUNCTUATION", + "PUREKILLER", + "QAAC", + "QAAI", + "QAF", + "QAPH", + "QMARK", + "QU", + "QUOTATION", + "QUOTATIONMARK", + "R", + "RADICAL", + "REGIONALINDICATOR", + "REGISTERSHIFTER", + "REH", + "REJANG", + "REORDERINGKILLER", + "REVERSEDPE", + "RI", + "RIGHT", + "RIGHTJOINING", + "RIGHTTOLEFT", + "RIGHTTOLEFTEMBEDDING", + "RIGHTTOLEFTISOLATE", + "RIGHTTOLEFTOVERRIDE", + "RJNG", + "RLE", + "RLI", + "RLO", + "ROHG", + "ROHINGYAYEH", + "RUMI", + "RUMINUMERALSYMBOLS", + "RUNIC", + "RUNR", + "S", + "S&", + "SA", + "SAD", + "SADHE", + "SAMARITAN", + "SAMR", + "SARB", + "SAUR", + "SAURASHTRA", + "SB", + "SC", + "SCONTINUE", + "SCRIPT", + "SCRIPTEXTENSIONS", + "SCX", + "SD", + "SE", + "SEEN", + "SEGMENTSEPARATOR", + "SEMKATH", + "SENTENCEBREAK", + "SENTENCETERMINAL", + "SEP", + "SEPARATOR", + "SG", + "SGNW", + "SHARADA", + "SHAVIAN", + "SHAW", + "SHIN", + "SHORTHANDFORMATCONTROLS", + "SHRD", + "SIDD", + "SIDDHAM", + "SIGNWRITING", + "SIND", + "SINGLEQUOTE", + "SINH", + "SINHALA", + "SINHALAARCHAICNUMBERS", + "SK", + "SM", + "SMALL", + "SMALLFORMS", + "SMALLFORMVARIANTS", + "SMALLKANAEXT", + "SMALLKANAEXTENSION", + "SML", + "SO", + "SOFTDOTTED", + "SOGD", + "SOGDIAN", + "SOGO", + "SORA", + "SORASOMPENG", + "SOYO", + "SOYOMBO", + "SP", + "SPACE", + "SPACESEPARATOR", + "SPACINGMARK", + "SPACINGMODIFIERLETTERS", + "SPECIALS", + "SQ", + "SQR", + "SQUARE", + "ST", + "STERM", + "STRAIGHTWAW", + "SUB", + "SUND", + "SUNDANESE", + "SUNDANESESUP", + "SUNDANESESUPPLEMENT", + "SUNU", + "SUNUWAR", + "SUP", + "SUPARROWSA", + "SUPARROWSB", + "SUPARROWSC", + "SUPER", + "SUPERANDSUB", + "SUPERSCRIPTSANDSUBSCRIPTS", + "SUPMATHOPERATORS", + "SUPPLEMENTALARROWSA", + "SUPPLEMENTALARROWSB", + "SUPPLEMENTALARROWSC", + "SUPPLEMENTALMATHEMATICALOPERATORS", + "SUPPLEMENTALPUNCTUATION", + "SUPPLEMENTALSYMBOLSANDPICTOGRAPHS", + "SUPPLEMENTARYPRIVATEUSEAREAA", + "SUPPLEMENTARYPRIVATEUSEAREAB", + "SUPPUAA", + "SUPPUAB", + "SUPPUNCTUATION", + "SUPSYMBOLSANDPICTOGRAPHS", + "SURROGATE", + "SUTTONSIGNWRITING", + "SWASHKAF", + "SY", + "SYLLABLEMODIFIER", + "SYLO", + "SYLOTINAGRI", + "SYMBOL", + "SYMBOLSANDPICTOGRAPHSEXTA", + "SYMBOLSANDPICTOGRAPHSEXTENDEDA", + "SYMBOLSFORLEGACYCOMPUTING", + "SYMBOLSFORLEGACYCOMPUTINGSUP", + "SYMBOLSFORLEGACYCOMPUTINGSUPPLEMENT", + "SYRC", + "SYRIAC", + "SYRIACSUP", + "SYRIACSUPPLEMENT", + "SYRIACWAW", + "T", + "TAGALOG", + "TAGB", + "TAGBANWA", + "TAGS", + "TAH", + "TAILE", + "TAITHAM", + "TAIVIET", + "TAIXUANJING", + "TAIXUANJINGSYMBOLS", + "TAKR", + "TAKRI", + "TALE", + "TALU", + "TAMIL", + "TAMILSUP", + "TAMILSUPPLEMENT", + "TAML", + "TANG", + "TANGSA", + "TANGUT", + "TANGUTCOMPONENTS", + "TANGUTSUP", + "TANGUTSUPPLEMENT", + "TAVT", + "TAW", + "TEHMARBUTA", + "TEHMARBUTAGOAL", + "TELU", + "TELUGU", + "TERM", + "TERMINALPUNCTUATION", + "TETH", + "TFNG", + "TGLG", + "THAA", + "THAANA", + "THAI", + "THINYEH", + "TIBETAN", + "TIBT", + "TIFINAGH", + "TIRH", + "TIRHUTA", + "TITLECASELETTER", + "TNSA", + "TODHRI", + "TODR", + "TONELETTER", + "TONEMARK", + "TOP", + "TOPANDBOTTOM", + "TOPANDBOTTOMANDLEFT", + "TOPANDBOTTOMANDRIGHT", + "TOPANDLEFT", + "TOPANDLEFTANDRIGHT", + "TOPANDRIGHT", + "TOTO", + "TRAILINGJAMO", + "TRANSPARENT", + "TRANSPORTANDMAP", + "TRANSPORTANDMAPSYMBOLS", + "TRUE", + "TULUTIGALARI", + "TUTG", + "U", + "UCAS", + "UCASEXT", + "UCASEXTA", + "UGAR", + "UGARITIC", + "UIDEO", + "UNASSIGNED", + "UNIFIEDCANADIANABORIGINALSYLLABICS", + "UNIFIEDCANADIANABORIGINALSYLLABICSEXTENDED", + "UNIFIEDCANADIANABORIGINALSYLLABICSEXTENDEDA", + "UNIFIEDIDEOGRAPH", + "UNKNOWN", + "UP", + "UPPER", + "UPPERCASE", + "UPPERCASELETTER", + "V", + "VAI", + "VAII", + "VARIATIONSELECTOR", + "VARIATIONSELECTORS", + "VARIATIONSELECTORSSUPPLEMENT", + "VEDICEXT", + "VEDICEXTENSIONS", + "VERT", + "VERTICAL", + "VERTICALFORMS", + "VERTICALTAIL", + "VERTSPACE", + "VF", + "VI", + "VIRAMA", + "VIRAMAFINAL", + "VISARGA", + "VISUALORDERLEFT", + "VITH", + "VITHKUQI", + "VOWEL", + "VOWELDEPENDENT", + "VOWELINDEPENDENT", + "VOWELJAMO", + "VR", + "VS", + "VSSUP", + "W", + "WANCHO", + "WARA", + "WARANGCITI", + "WAW", + "WB", + "WCHO", + "WHITESPACE", + "WIDE", + "WJ", + "WORD", + "WORDBREAK", + "WORDJOINER", + "WS", + "WSEGSPACE", + "WSPACE", + "XDIGIT", + "XIDC", + "XIDCONTINUE", + "XIDS", + "XIDSTART", + "XPEO", + "XSUX", + "XX", + "Y", + "YEH", + "YEHBARREE", + "YEHWITHTAIL", + "YES", + "YEZI", + "YEZIDI", + "YI", + "YIII", + "YIJING", + "YIJINGHEXAGRAMSYMBOLS", + "YIRADICALS", + "YISYLLABLES", + "YUDH", + "YUDHHE", + "Z", + "Z&", + "ZAIN", + "ZANABAZARSQUARE", + "ZANB", + "ZHAIN", + "ZINH", + "ZL", + "ZNAMENNYMUSIC", + "ZNAMENNYMUSICALNOTATION", + "ZP", + "ZS", + "ZW", + "ZWJ", + "ZWSPACE", + "ZYYY", + "ZZZZ", +}; + +/* Properties. */ +RE_Property re_properties[] = { + { 195, 0, 0}, /* ALPHABETIC */ + { 194, 0, 0}, /* ALPHA */ + { 198, 1, 0}, /* ALPHANUMERIC */ + { 193, 1, 0}, /* ALNUM */ + { 206, 2, 0}, /* ANY */ + { 233, 3, 0}, /* ASCIIHEXDIGIT */ + { 179, 3, 0}, /* AHEX */ + { 274, 4, 1}, /* BIDICLASS */ + { 263, 4, 1}, /* BC */ + { 275, 5, 0}, /* BIDICONTROL */ + { 273, 5, 0}, /* BIDIC */ + { 277, 6, 0}, /* BIDIMIRRORED */ + { 276, 6, 0}, /* BIDIM */ + { 281, 7, 0}, /* BLANK */ + { 283, 8, 2}, /* BLOCK */ + { 282, 8, 2}, /* BLK */ + { 320, 9, 3}, /* CANONICALCOMBININGCLASS */ + { 332, 9, 3}, /* CCC */ + { 326, 10, 0}, /* CASED */ + { 328, 11, 0}, /* CASEIGNORABLE */ + { 385, 11, 0}, /* CI */ + { 373, 12, 0}, /* CHANGESWHENCASEFOLDED */ + { 476, 12, 0}, /* CWCF */ + { 374, 13, 0}, /* CHANGESWHENCASEMAPPED */ + { 477, 13, 0}, /* CWCM */ + { 375, 14, 0}, /* CHANGESWHENLOWERCASED */ + { 478, 14, 0}, /* CWL */ + { 376, 15, 0}, /* CHANGESWHENTITLECASED */ + { 479, 15, 0}, /* CWT */ + { 377, 16, 0}, /* CHANGESWHENUPPERCASED */ + { 480, 16, 0}, /* CWU */ + { 501, 17, 0}, /* DASH */ + { 507, 18, 4}, /* DECOMPOSITIONTYPE */ + { 538, 18, 4}, /* DT */ + { 508, 19, 0}, /* DEFAULTIGNORABLECODEPOINT */ + { 518, 19, 0}, /* DI */ + { 510, 20, 0}, /* DEPRECATED */ + { 509, 20, 0}, /* DEP */ + { 520, 21, 0}, /* DIACRITIC */ + { 519, 21, 0}, /* DIA */ + { 545, 22, 5}, /* EASTASIANWIDTH */ + { 543, 22, 5}, /* EA */ + { 563, 23, 0}, /* EMOJI */ + { 564, 24, 0}, /* EMOJICOMPONENT */ + { 550, 24, 0}, /* ECOMP */ + { 565, 25, 0}, /* EMOJIMODIFIER */ + { 561, 25, 0}, /* EMOD */ + { 566, 26, 0}, /* EMOJIMODIFIERBASE */ + { 547, 26, 0}, /* EBASE */ + { 567, 27, 0}, /* EMOJIPRESENTATION */ + { 580, 27, 0}, /* EPRES */ + { 600, 28, 0}, /* EXTENDEDPICTOGRAPHIC */ + { 603, 28, 0}, /* EXTPICT */ + { 601, 29, 0}, /* EXTENDER */ + { 598, 29, 0}, /* EXT */ + { 629, 30, 6}, /* GENERALCATEGORY */ + { 626, 30, 6}, /* GC */ + { 653, 31, 0}, /* GRAPH */ + { 654, 32, 0}, /* GRAPHEMEBASE */ + { 658, 32, 0}, /* GRBASE */ + { 655, 33, 7}, /* GRAPHEMECLUSTERBREAK */ + { 627, 33, 7}, /* GCB */ + { 656, 34, 0}, /* GRAPHEMEEXTEND */ + { 664, 34, 0}, /* GREXT */ + { 657, 35, 0}, /* GRAPHEMELINK */ + { 665, 35, 0}, /* GRLINK */ + { 690, 36, 8}, /* HANGULSYLLABLETYPE */ + { 721, 36, 8}, /* HST */ + { 709, 37, 0}, /* HEXDIGIT */ + { 708, 37, 0}, /* HEX */ + { 719, 38, 0}, /* HORIZSPACE */ + { 673, 38, 0}, /* H */ + { 724, 39, 0}, /* HYPHEN */ + { 727, 40, 0}, /* IDCOMPATMATHCONTINUE */ + { 728, 41, 0}, /* IDCOMPATMATHSTART */ + { 729, 42, 0}, /* IDCONTINUE */ + { 726, 42, 0}, /* IDC */ + { 731, 43, 0}, /* IDEOGRAPHIC */ + { 730, 43, 0}, /* IDEO */ + { 737, 44, 0}, /* IDSBINARYOPERATOR */ + { 736, 44, 0}, /* IDSB */ + { 739, 45, 0}, /* IDSTART */ + { 735, 45, 0}, /* IDS */ + { 740, 46, 0}, /* IDSTRINARYOPERATOR */ + { 738, 46, 0}, /* IDST */ + { 742, 47, 0}, /* IDSUNARYOPERATOR */ + { 741, 47, 0}, /* IDSU */ + { 746, 48, 9}, /* INDICCONJUNCTBREAK */ + { 745, 48, 9}, /* INCB */ + { 748, 49, 10}, /* INDICPOSITIONALCATEGORY */ + { 756, 49, 10}, /* INPC */ + { 750, 50, 11}, /* INDICSYLLABICCATEGORY */ + { 757, 50, 11}, /* INSC */ + { 779, 51, 0}, /* JOINCONTROL */ + { 777, 51, 0}, /* JOINC */ + { 781, 52, 12}, /* JOININGGROUP */ + { 775, 52, 12}, /* JG */ + { 782, 53, 13}, /* JOININGTYPE */ + { 783, 53, 13}, /* JT */ + { 880, 54, 14}, /* LINEBREAK */ + { 855, 54, 14}, /* LB */ + { 891, 55, 0}, /* LOGICALORDEREXCEPTION */ + { 890, 55, 0}, /* LOE */ + { 893, 56, 0}, /* LOWERCASE */ + { 892, 56, 0}, /* LOWER */ + { 965, 57, 0}, /* MATH */ + {1012, 58, 0}, /* MODIFIERCOMBININGMARK */ + { 975, 58, 0}, /* MCM */ + {1059, 59, 15}, /* NFCQUICKCHECK */ + {1058, 59, 15}, /* NFCQC */ + {1061, 60, 16}, /* NFDQUICKCHECK */ + {1060, 60, 16}, /* NFDQC */ + {1063, 61, 15}, /* NFKCQUICKCHECK */ + {1062, 61, 15}, /* NFKCQC */ + {1065, 62, 16}, /* NFKDQUICKCHECK */ + {1064, 62, 16}, /* NFKDQC */ + {1074, 63, 0}, /* NONCHARACTERCODEPOINT */ + {1051, 63, 0}, /* NCHAR */ + {1094, 64, 17}, /* NUMERICTYPE */ + {1087, 64, 17}, /* NT */ + {1095, 65, 18}, /* NUMERICVALUE */ + {1098, 65, 18}, /* NV */ + {1138, 66, 0}, /* OTHERALPHABETIC */ + {1101, 66, 0}, /* OALPHA */ + {1139, 67, 0}, /* OTHERDEFAULTIGNORABLECODEPOINT */ + {1103, 67, 0}, /* ODI */ + {1140, 68, 0}, /* OTHERGRAPHEMEEXTEND */ + {1106, 68, 0}, /* OGREXT */ + {1141, 69, 0}, /* OTHERIDCONTINUE */ + {1107, 69, 0}, /* OIDC */ + {1142, 70, 0}, /* OTHERIDSTART */ + {1108, 70, 0}, /* OIDS */ + {1144, 71, 0}, /* OTHERLOWERCASE */ + {1122, 71, 0}, /* OLOWER */ + {1145, 72, 0}, /* OTHERMATH */ + {1123, 72, 0}, /* OMATH */ + {1150, 73, 0}, /* OTHERUPPERCASE */ + {1153, 73, 0}, /* OUPPER */ + {1164, 74, 0}, /* PATTERNSYNTAX */ + {1163, 74, 0}, /* PATSYN */ + {1165, 75, 0}, /* PATTERNWHITESPACE */ + {1166, 75, 0}, /* PATWS */ + {1195, 76, 0}, /* POSIXALNUM */ + {1196, 77, 0}, /* POSIXDIGIT */ + {1197, 78, 0}, /* POSIXPUNCT */ + {1198, 79, 0}, /* POSIXXDIGIT */ + {1204, 80, 0}, /* PREPENDEDCONCATENATIONMARK */ + {1170, 80, 0}, /* PCM */ + {1205, 81, 0}, /* PRINT */ + {1222, 82, 0}, /* QUOTATIONMARK */ + {1219, 82, 0}, /* QMARK */ + {1224, 83, 0}, /* RADICAL */ + {1225, 84, 0}, /* REGIONALINDICATOR */ + {1231, 84, 0}, /* RI */ + {1261, 85, 19}, /* SCRIPT */ + {1259, 85, 19}, /* SC */ + {1262, 86, 19}, /* SCRIPTEXTENSIONS */ + {1263, 86, 19}, /* SCX */ + {1269, 87, 20}, /* SENTENCEBREAK */ + {1258, 87, 20}, /* SB */ + {1270, 88, 0}, /* SENTENCETERMINAL */ + {1316, 88, 0}, /* STERM */ + {1298, 89, 0}, /* SOFTDOTTED */ + {1264, 89, 0}, /* SD */ + {1395, 90, 0}, /* TERMINALPUNCTUATION */ + {1394, 90, 0}, /* TERM */ + {1440, 91, 0}, /* UNIFIEDIDEOGRAPH */ + {1435, 91, 0}, /* UIDEO */ + {1444, 92, 0}, /* UPPERCASE */ + {1443, 92, 0}, /* UPPER */ + {1449, 93, 0}, /* VARIATIONSELECTOR */ + {1472, 93, 0}, /* VS */ + {1458, 94, 0}, /* VERTSPACE */ + {1446, 94, 0}, /* V */ + {1481, 95, 0}, /* WHITESPACE */ + {1489, 95, 0}, /* WSPACE */ + {1307, 95, 0}, /* SPACE */ + {1484, 96, 0}, /* WORD */ + {1485, 97, 21}, /* WORDBREAK */ + {1479, 97, 21}, /* WB */ + {1490, 98, 0}, /* XDIGIT */ + {1492, 99, 0}, /* XIDCONTINUE */ + {1491, 99, 0}, /* XIDC */ + {1494, 100, 0}, /* XIDSTART */ + {1493, 100, 0}, /* XIDS */ +}; + +/* Property values. */ +RE_PropertyValue re_property_values[] = { + {1070, 0, 0}, /* NO */ + {1037, 0, 0}, /* N */ + { 604, 0, 0}, /* F */ + { 605, 0, 0}, /* FALSE */ + {1502, 0, 1}, /* YES */ + {1498, 0, 1}, /* Y */ + {1363, 0, 1}, /* T */ + {1426, 0, 1}, /* TRUE */ + {1234, 1, 0}, /* RIGHTTOLEFT */ + {1223, 1, 0}, /* R */ + { 293, 1, 1}, /* BOUNDARYNEUTRAL */ + { 285, 1, 1}, /* BN */ + {1267, 1, 2}, /* SEGMENTSEPARATOR */ + {1248, 1, 2}, /* S */ + {1162, 1, 3}, /* PARAGRAPHSEPARATOR */ + { 248, 1, 3}, /* B */ + {1481, 1, 4}, /* WHITESPACE */ + {1487, 1, 4}, /* WS */ + {1146, 1, 5}, /* OTHERNEUTRAL */ + {1124, 1, 5}, /* ON */ + { 595, 1, 6}, /* EUROPEANTERMINATOR */ + { 582, 1, 6}, /* ET */ + { 594, 1, 7}, /* EUROPEANSEPARATOR */ + { 581, 1, 7}, /* ES */ + { 439, 1, 8}, /* COMMONSEPARATOR */ + { 470, 1, 8}, /* CS */ + { 593, 1, 9}, /* EUROPEANNUMBER */ + { 569, 1, 9}, /* EN */ + { 862, 1, 10}, /* LEFTTORIGHT */ + { 827, 1, 10}, /* L */ + {1078, 1, 11}, /* NONSPACINGMARK */ + {1086, 1, 11}, /* NSM */ + { 220, 1, 12}, /* ARABICNUMBER */ + { 200, 1, 12}, /* AN */ + { 217, 1, 13}, /* ARABICLETTER */ + { 187, 1, 13}, /* AL */ + { 863, 1, 14}, /* LEFTTORIGHTEMBEDDING */ + { 896, 1, 14}, /* LRE */ + {1235, 1, 15}, /* RIGHTTOLEFTEMBEDDING */ + {1239, 1, 15}, /* RLE */ + {1193, 1, 16}, /* POPDIRECTIONALFORMAT */ + {1172, 1, 16}, /* PDF */ + { 865, 1, 17}, /* LEFTTORIGHTOVERRIDE */ + { 898, 1, 17}, /* LRO */ + {1237, 1, 18}, /* RIGHTTOLEFTOVERRIDE */ + {1241, 1, 18}, /* RLO */ + { 864, 1, 19}, /* LEFTTORIGHTISOLATE */ + { 897, 1, 19}, /* LRI */ + {1236, 1, 20}, /* RIGHTTOLEFTISOLATE */ + {1240, 1, 20}, /* RLI */ + { 613, 1, 21}, /* FIRSTSTRONGISOLATE */ + { 619, 1, 21}, /* FSI */ + {1194, 1, 22}, /* POPDIRECTIONALISOLATE */ + {1173, 1, 22}, /* PDI */ + {1071, 2, 0}, /* NOBLOCK */ + {1049, 2, 0}, /* NB */ + { 257, 2, 1}, /* BASICLATIN */ + { 232, 2, 1}, /* ASCII */ + { 837, 2, 2}, /* LATIN1SUPPLEMENT */ + { 836, 2, 2}, /* LATIN1SUP */ + { 835, 2, 2}, /* LATIN1 */ + { 844, 2, 3}, /* LATINEXTENDEDA */ + { 838, 2, 3}, /* LATINEXTA */ + { 846, 2, 4}, /* LATINEXTENDEDB */ + { 840, 2, 4}, /* LATINEXTB */ + { 765, 2, 5}, /* IPAEXTENSIONS */ + { 764, 2, 5}, /* IPAEXT */ + {1310, 2, 6}, /* SPACINGMODIFIERLETTERS */ + {1014, 2, 6}, /* MODIFIERLETTERS */ + { 430, 2, 7}, /* COMBININGDIACRITICALMARKS */ + { 521, 2, 7}, /* DIACRITICALS */ + { 660, 2, 8}, /* GREEKANDCOPTIC */ + { 659, 2, 8}, /* GREEK */ + { 484, 2, 9}, /* CYRILLIC */ + { 494, 2, 10}, /* CYRILLICSUPPLEMENT */ + { 493, 2, 10}, /* CYRILLICSUP */ + { 495, 2, 10}, /* CYRILLICSUPPLEMENTARY */ + { 227, 2, 11}, /* ARMENIAN */ + { 703, 2, 12}, /* HEBREW */ + { 210, 2, 13}, /* ARABIC */ + {1359, 2, 14}, /* SYRIAC */ + { 226, 2, 15}, /* ARABICSUPPLEMENT */ + { 225, 2, 15}, /* ARABICSUP */ + {1400, 2, 16}, /* THAANA */ + {1067, 2, 17}, /* NKO */ + {1253, 2, 18}, /* SAMARITAN */ + { 930, 2, 19}, /* MANDAIC */ + {1361, 2, 20}, /* SYRIACSUPPLEMENT */ + {1360, 2, 20}, /* SYRIACSUP */ + { 215, 2, 21}, /* ARABICEXTENDEDB */ + { 212, 2, 21}, /* ARABICEXTB */ + { 214, 2, 22}, /* ARABICEXTENDEDA */ + { 211, 2, 22}, /* ARABICEXTA */ + { 513, 2, 23}, /* DEVANAGARI */ + { 269, 2, 24}, /* BENGALI */ + { 670, 2, 25}, /* GURMUKHI */ + { 666, 2, 26}, /* GUJARATI */ + {1129, 2, 27}, /* ORIYA */ + {1378, 2, 28}, /* TAMIL */ + {1393, 2, 29}, /* TELUGU */ + { 801, 2, 30}, /* KANNADA */ + { 917, 2, 31}, /* MALAYALAM */ + {1287, 2, 32}, /* SINHALA */ + {1401, 2, 33}, /* THAI */ + { 832, 2, 34}, /* LAO */ + {1403, 2, 35}, /* TIBETAN */ + {1029, 2, 36}, /* MYANMAR */ + { 635, 2, 37}, /* GEORGIAN */ + { 686, 2, 38}, /* HANGULJAMO */ + { 770, 2, 38}, /* JAMO */ + { 584, 2, 39}, /* ETHIOPIC */ + { 592, 2, 40}, /* ETHIOPICSUPPLEMENT */ + { 591, 2, 40}, /* ETHIOPICSUP */ + { 379, 2, 41}, /* CHEROKEE */ + {1437, 2, 42}, /* UNIFIEDCANADIANABORIGINALSYLLABICS */ + {1430, 2, 42}, /* UCAS */ + { 318, 2, 42}, /* CANADIANSYLLABICS */ + {1105, 2, 43}, /* OGHAM */ + {1246, 2, 44}, /* RUNIC */ + {1364, 2, 45}, /* TAGALOG */ + { 698, 2, 46}, /* HANUNOO */ + { 309, 2, 47}, /* BUHID */ + {1366, 2, 48}, /* TAGBANWA */ + { 814, 2, 49}, /* KHMER */ + {1019, 2, 50}, /* MONGOLIAN */ + {1438, 2, 51}, /* UNIFIEDCANADIANABORIGINALSYLLABICSEXTENDED */ + {1431, 2, 51}, /* UCASEXT */ + { 873, 2, 52}, /* LIMBU */ + {1369, 2, 53}, /* TAILE */ + {1056, 2, 54}, /* NEWTAILUE */ + { 815, 2, 55}, /* KHMERSYMBOLS */ + { 307, 2, 56}, /* BUGINESE */ + {1370, 2, 57}, /* TAITHAM */ + { 431, 2, 58}, /* COMBININGDIACRITICALMARKSEXTENDED */ + { 522, 2, 58}, /* DIACRITICALSEXT */ + { 252, 2, 59}, /* BALINESE */ + {1320, 2, 60}, /* SUNDANESE */ + { 260, 2, 61}, /* BATAK */ + { 867, 2, 62}, /* LEPCHA */ + {1109, 2, 63}, /* OLCHIKI */ + { 491, 2, 64}, /* CYRILLICEXTENDEDC */ + { 487, 2, 64}, /* CYRILLICEXTC */ + { 637, 2, 65}, /* GEORGIANEXTENDED */ + { 636, 2, 65}, /* GEORGIANEXT */ + {1322, 2, 66}, /* SUNDANESESUPPLEMENT */ + {1321, 2, 66}, /* SUNDANESESUP */ + {1453, 2, 67}, /* VEDICEXTENSIONS */ + {1452, 2, 67}, /* VEDICEXT */ + {1186, 2, 68}, /* PHONETICEXTENSIONS */ + {1185, 2, 68}, /* PHONETICEXT */ + {1187, 2, 69}, /* PHONETICEXTENSIONSSUPPLEMENT */ + {1188, 2, 69}, /* PHONETICEXTSUP */ + { 433, 2, 70}, /* COMBININGDIACRITICALMARKSSUPPLEMENT */ + { 524, 2, 70}, /* DIACRITICALSSUP */ + { 845, 2, 71}, /* LATINEXTENDEDADDITIONAL */ + { 839, 2, 71}, /* LATINEXTADDITIONAL */ + { 662, 2, 72}, /* GREEKEXTENDED */ + { 661, 2, 72}, /* GREEKEXT */ + { 630, 2, 73}, /* GENERALPUNCTUATION */ + {1213, 2, 73}, /* PUNCTUATION */ + {1331, 2, 74}, /* SUPERSCRIPTSANDSUBSCRIPTS */ + {1330, 2, 74}, /* SUPERANDSUB */ + { 475, 2, 75}, /* CURRENCYSYMBOLS */ + { 432, 2, 76}, /* COMBININGDIACRITICALMARKSFORSYMBOLS */ + { 523, 2, 76}, /* DIACRITICALSFORSYMBOLS */ + { 436, 2, 76}, /* COMBININGMARKSFORSYMBOLS */ + { 869, 2, 77}, /* LETTERLIKESYMBOLS */ + {1091, 2, 78}, /* NUMBERFORMS */ + { 230, 2, 79}, /* ARROWS */ + { 968, 2, 80}, /* MATHEMATICALOPERATORS */ + { 969, 2, 80}, /* MATHOPERATORS */ + {1002, 2, 81}, /* MISCELLANEOUSTECHNICAL */ + {1007, 2, 81}, /* MISCTECHNICAL */ + { 460, 2, 82}, /* CONTROLPICTURES */ + {1128, 2, 83}, /* OPTICALCHARACTERRECOGNITION */ + {1102, 2, 83}, /* OCR */ + { 572, 2, 84}, /* ENCLOSEDALPHANUMERICS */ + { 571, 2, 84}, /* ENCLOSEDALPHANUM */ + { 294, 2, 85}, /* BOXDRAWING */ + { 284, 2, 86}, /* BLOCKELEMENTS */ + { 631, 2, 87}, /* GEOMETRICSHAPES */ + { 999, 2, 88}, /* MISCELLANEOUSSYMBOLS */ + {1006, 2, 88}, /* MISCSYMBOLS */ + { 527, 2, 89}, /* DINGBATS */ + { 997, 2, 90}, /* MISCELLANEOUSMATHEMATICALSYMBOLSA */ + {1003, 2, 90}, /* MISCMATHSYMBOLSA */ + {1333, 2, 91}, /* SUPPLEMENTALARROWSA */ + {1326, 2, 91}, /* SUPARROWSA */ + { 301, 2, 92}, /* BRAILLEPATTERNS */ + { 300, 2, 92}, /* BRAILLE */ + {1334, 2, 93}, /* SUPPLEMENTALARROWSB */ + {1327, 2, 93}, /* SUPARROWSB */ + { 998, 2, 94}, /* MISCELLANEOUSMATHEMATICALSYMBOLSB */ + {1004, 2, 94}, /* MISCMATHSYMBOLSB */ + {1336, 2, 95}, /* SUPPLEMENTALMATHEMATICALOPERATORS */ + {1332, 2, 95}, /* SUPMATHOPERATORS */ + {1000, 2, 96}, /* MISCELLANEOUSSYMBOLSANDARROWS */ + { 996, 2, 96}, /* MISCARROWS */ + { 642, 2, 97}, /* GLAGOLITIC */ + { 847, 2, 98}, /* LATINEXTENDEDC */ + { 841, 2, 98}, /* LATINEXTC */ + { 462, 2, 99}, /* COPTIC */ + { 639, 2, 100}, /* GEORGIANSUPPLEMENT */ + { 638, 2, 100}, /* GEORGIANSUP */ + {1405, 2, 101}, /* TIFINAGH */ + { 588, 2, 102}, /* ETHIOPICEXTENDED */ + { 585, 2, 102}, /* ETHIOPICEXT */ + { 489, 2, 103}, /* CYRILLICEXTENDEDA */ + { 485, 2, 103}, /* CYRILLICEXTA */ + {1337, 2, 104}, /* SUPPLEMENTALPUNCTUATION */ + {1343, 2, 104}, /* SUPPUNCTUATION */ + { 407, 2, 105}, /* CJKRADICALSSUPPLEMENT */ + { 406, 2, 105}, /* CJKRADICALSSUP */ + { 800, 2, 106}, /* KANGXIRADICALS */ + { 799, 2, 106}, /* KANGXI */ + { 732, 2, 107}, /* IDEOGRAPHICDESCRIPTIONCHARACTERS */ + { 726, 2, 107}, /* IDC */ + { 410, 2, 108}, /* CJKSYMBOLSANDPUNCTUATION */ + { 409, 2, 108}, /* CJKSYMBOLS */ + { 714, 2, 109}, /* HIRAGANA */ + { 804, 2, 110}, /* KATAKANA */ + { 287, 2, 111}, /* BOPOMOFO */ + { 685, 2, 112}, /* HANGULCOMPATIBILITYJAMO */ + { 441, 2, 112}, /* COMPATJAMO */ + { 798, 2, 113}, /* KANBUN */ + { 289, 2, 114}, /* BOPOMOFOEXTENDED */ + { 288, 2, 114}, /* BOPOMOFOEXT */ + { 408, 2, 115}, /* CJKSTROKES */ + { 807, 2, 116}, /* KATAKANAPHONETICEXTENSIONS */ + { 805, 2, 116}, /* KATAKANAEXT */ + { 576, 2, 117}, /* ENCLOSEDCJKLETTERSANDMONTHS */ + { 575, 2, 117}, /* ENCLOSEDCJK */ + { 391, 2, 118}, /* CJKCOMPATIBILITY */ + { 389, 2, 118}, /* CJKCOMPAT */ + { 412, 2, 119}, /* CJKUNIFIEDIDEOGRAPHSEXTENSIONA */ + { 397, 2, 119}, /* CJKEXTA */ + {1508, 2, 120}, /* YIJINGHEXAGRAMSYMBOLS */ + {1507, 2, 120}, /* YIJING */ + { 411, 2, 121}, /* CJKUNIFIEDIDEOGRAPHS */ + { 388, 2, 121}, /* CJK */ + {1510, 2, 122}, /* YISYLLABLES */ + {1509, 2, 123}, /* YIRADICALS */ + { 884, 2, 124}, /* LISU */ + {1447, 2, 125}, /* VAI */ + { 490, 2, 126}, /* CYRILLICEXTENDEDB */ + { 486, 2, 126}, /* CYRILLICEXTB */ + { 254, 2, 127}, /* BAMUM */ + {1016, 2, 128}, /* MODIFIERTONELETTERS */ + { 848, 2, 129}, /* LATINEXTENDEDD */ + { 842, 2, 129}, /* LATINEXTD */ + {1351, 2, 130}, /* SYLOTINAGRI */ + { 438, 2, 131}, /* COMMONINDICNUMBERFORMS */ + { 747, 2, 131}, /* INDICNUMBERFORMS */ + {1178, 2, 132}, /* PHAGSPA */ + {1257, 2, 133}, /* SAURASHTRA */ + { 516, 2, 134}, /* DEVANAGARIEXTENDED */ + { 514, 2, 134}, /* DEVANAGARIEXT */ + { 809, 2, 135}, /* KAYAHLI */ + {1228, 2, 136}, /* REJANG */ + { 687, 2, 137}, /* HANGULJAMOEXTENDEDA */ + { 771, 2, 137}, /* JAMOEXTA */ + { 774, 2, 138}, /* JAVANESE */ + {1034, 2, 139}, /* MYANMAREXTENDEDB */ + {1031, 2, 139}, /* MYANMAREXTB */ + { 372, 2, 140}, /* CHAM */ + {1033, 2, 141}, /* MYANMAREXTENDEDA */ + {1030, 2, 141}, /* MYANMAREXTA */ + {1371, 2, 142}, /* TAIVIET */ + { 984, 2, 143}, /* MEETEIMAYEKEXTENSIONS */ + { 983, 2, 143}, /* MEETEIMAYEKEXT */ + { 589, 2, 144}, /* ETHIOPICEXTENDEDA */ + { 586, 2, 144}, /* ETHIOPICEXTA */ + { 849, 2, 145}, /* LATINEXTENDEDE */ + { 843, 2, 145}, /* LATINEXTE */ + { 381, 2, 146}, /* CHEROKEESUPPLEMENT */ + { 380, 2, 146}, /* CHEROKEESUP */ + { 982, 2, 147}, /* MEETEIMAYEK */ + { 689, 2, 148}, /* HANGULSYLLABLES */ + { 684, 2, 148}, /* HANGUL */ + { 688, 2, 149}, /* HANGULJAMOEXTENDEDB */ + { 772, 2, 149}, /* JAMOEXTB */ + { 712, 2, 150}, /* HIGHSURROGATES */ + { 710, 2, 151}, /* HIGHPRIVATEUSESURROGATES */ + { 711, 2, 151}, /* HIGHPUSURROGATES */ + { 895, 2, 152}, /* LOWSURROGATES */ + {1207, 2, 153}, /* PRIVATEUSEAREA */ + {1211, 2, 153}, /* PUA */ + {1206, 2, 153}, /* PRIVATEUSE */ + { 393, 2, 154}, /* CJKCOMPATIBILITYIDEOGRAPHS */ + { 395, 2, 154}, /* CJKCOMPATIDEOGRAPHS */ + { 197, 2, 155}, /* ALPHABETICPRESENTATIONFORMS */ + { 196, 2, 155}, /* ALPHABETICPF */ + { 223, 2, 156}, /* ARABICPRESENTATIONFORMSA */ + { 221, 2, 156}, /* ARABICPFA */ + {1450, 2, 157}, /* VARIATIONSELECTORS */ + {1472, 2, 157}, /* VS */ + {1456, 2, 158}, /* VERTICALFORMS */ + { 434, 2, 159}, /* COMBININGHALFMARKS */ + { 678, 2, 159}, /* HALFMARKS */ + { 392, 2, 160}, /* CJKCOMPATIBILITYFORMS */ + { 390, 2, 160}, /* CJKCOMPATFORMS */ + {1293, 2, 161}, /* SMALLFORMVARIANTS */ + {1292, 2, 161}, /* SMALLFORMS */ + { 224, 2, 162}, /* ARABICPRESENTATIONFORMSB */ + { 222, 2, 162}, /* ARABICPFB */ + { 680, 2, 163}, /* HALFWIDTHANDFULLWIDTHFORMS */ + { 677, 2, 163}, /* HALFANDFULLFORMS */ + {1311, 2, 164}, /* SPECIALS */ + { 879, 2, 165}, /* LINEARBSYLLABARY */ + { 878, 2, 166}, /* LINEARBIDEOGRAMS */ + { 174, 2, 167}, /* AEGEANNUMBERS */ + { 204, 2, 168}, /* ANCIENTGREEKNUMBERS */ + { 205, 2, 169}, /* ANCIENTSYMBOLS */ + {1180, 2, 170}, /* PHAISTOSDISC */ + {1179, 2, 170}, /* PHAISTOS */ + { 906, 2, 171}, /* LYCIAN */ + { 324, 2, 172}, /* CARIAN */ + { 463, 2, 173}, /* COPTICEPACTNUMBERS */ + {1112, 2, 174}, /* OLDITALIC */ + { 650, 2, 175}, /* GOTHIC */ + {1114, 2, 176}, /* OLDPERMIC */ + {1434, 2, 177}, /* UGARITIC */ + {1115, 2, 178}, /* OLDPERSIAN */ + { 511, 2, 179}, /* DESERET */ + {1276, 2, 180}, /* SHAVIAN */ + {1136, 2, 181}, /* OSMANYA */ + {1133, 2, 182}, /* OSAGE */ + { 557, 2, 183}, /* ELBASAN */ + { 329, 2, 184}, /* CAUCASIANALBANIAN */ + {1466, 2, 185}, /* VITHKUQI */ + {1410, 2, 186}, /* TODHRI */ + { 876, 2, 187}, /* LINEARA */ + { 850, 2, 188}, /* LATINEXTENDEDF */ + { 852, 2, 188}, /* LATINEXTF */ + { 482, 2, 189}, /* CYPRIOTSYLLABARY */ + { 743, 2, 190}, /* IMPERIALARAMAIC */ + {1161, 2, 191}, /* PALMYRENE */ + {1040, 2, 192}, /* NABATAEAN */ + { 700, 2, 193}, /* HATRAN */ + {1184, 2, 194}, /* PHOENICIAN */ + { 908, 2, 195}, /* LYDIAN */ + { 990, 2, 196}, /* MEROITICHIEROGLYPHS */ + { 989, 2, 197}, /* MEROITICCURSIVE */ + { 812, 2, 198}, /* KHAROSHTHI */ + {1117, 2, 199}, /* OLDSOUTHARABIAN */ + {1113, 2, 200}, /* OLDNORTHARABIAN */ + { 933, 2, 201}, /* MANICHAEAN */ + { 246, 2, 202}, /* AVESTAN */ + { 759, 2, 203}, /* INSCRIPTIONALPARTHIAN */ + { 758, 2, 204}, /* INSCRIPTIONALPAHLAVI */ + {1210, 2, 205}, /* PSALTERPAHLAVI */ + {1118, 2, 206}, /* OLDTURKIC */ + {1111, 2, 207}, /* OLDHUNGARIAN */ + { 692, 2, 208}, /* HANIFIROHINGYA */ + { 624, 2, 209}, /* GARAY */ + {1245, 2, 210}, /* RUMINUMERALSYMBOLS */ + {1244, 2, 210}, /* RUMI */ + {1504, 2, 211}, /* YEZIDI */ + { 216, 2, 212}, /* ARABICEXTENDEDC */ + { 213, 2, 212}, /* ARABICEXTC */ + {1116, 2, 213}, /* OLDSOGDIAN */ + {1300, 2, 214}, /* SOGDIAN */ + {1119, 2, 215}, /* OLDUYGHUR */ + { 383, 2, 216}, /* CHORASMIAN */ + { 559, 2, 217}, /* ELYMAIC */ + { 297, 2, 218}, /* BRAHMI */ + { 787, 2, 219}, /* KAITHI */ + {1303, 2, 220}, /* SORASOMPENG */ + { 371, 2, 221}, /* CHAKMA */ + { 911, 2, 222}, /* MAHAJANI */ + {1275, 2, 223}, /* SHARADA */ + {1288, 2, 224}, /* SINHALAARCHAICNUMBERS */ + { 818, 2, 225}, /* KHOJKI */ + {1026, 2, 226}, /* MULTANI */ + { 819, 2, 227}, /* KHUDAWADI */ + { 652, 2, 228}, /* GRANTHA */ + {1427, 2, 229}, /* TULUTIGALARI */ + {1054, 2, 230}, /* NEWA */ + {1407, 2, 231}, /* TIRHUTA */ + {1282, 2, 232}, /* SIDDHAM */ + {1011, 2, 233}, /* MODI */ + {1021, 2, 234}, /* MONGOLIANSUPPLEMENT */ + {1020, 2, 234}, /* MONGOLIANSUP */ + {1375, 2, 235}, /* TAKRI */ + {1035, 2, 236}, /* MYANMAREXTENDEDC */ + {1032, 2, 236}, /* MYANMAREXTC */ + { 180, 2, 237}, /* AHOM */ + { 530, 2, 238}, /* DOGRA */ + {1477, 2, 239}, /* WARANGCITI */ + { 528, 2, 240}, /* DIVESAKURU */ + {1045, 2, 241}, /* NANDINAGARI */ + {1516, 2, 242}, /* ZANABAZARSQUARE */ + {1305, 2, 243}, /* SOYOMBO */ + {1439, 2, 244}, /* UNIFIEDCANADIANABORIGINALSYLLABICSEXTENDEDA */ + {1432, 2, 244}, /* UCASEXTA */ + {1168, 2, 245}, /* PAUCINHAU */ + { 517, 2, 246}, /* DEVANAGARIEXTENDEDA */ + { 515, 2, 246}, /* DEVANAGARIEXTA */ + {1324, 2, 247}, /* SUNUWAR */ + { 271, 2, 248}, /* BHAIKSUKI */ + { 962, 2, 249}, /* MARCHEN */ + { 964, 2, 250}, /* MASARAMGONDI */ + { 669, 2, 251}, /* GUNJALAGONDI */ + { 916, 2, 252}, /* MAKASAR */ + { 808, 2, 253}, /* KAWI */ + { 886, 2, 254}, /* LISUSUPPLEMENT */ + { 885, 2, 254}, /* LISUSUP */ + {1380, 2, 255}, /* TAMILSUPPLEMENT */ + {1379, 2, 255}, /* TAMILSUP */ + { 471, 2, 256}, /* CUNEIFORM */ + { 473, 2, 257}, /* CUNEIFORMNUMBERSANDPUNCTUATION */ + { 472, 2, 257}, /* CUNEIFORMNUMBERS */ + { 544, 2, 258}, /* EARLYDYNASTICCUNEIFORM */ + { 483, 2, 259}, /* CYPROMINOAN */ + { 553, 2, 260}, /* EGYPTIANHIEROGLYPHS */ + { 552, 2, 261}, /* EGYPTIANHIEROGLYPHFORMATCONTROLS */ + { 555, 2, 262}, /* EGYPTIANHIEROGLYPHSEXTENDEDA */ + { 554, 2, 262}, /* EGYPTIANHIEROGLYPHSEXTA */ + { 201, 2, 263}, /* ANATOLIANHIEROGLYPHS */ + { 672, 2, 264}, /* GURUNGKHEMA */ + { 256, 2, 265}, /* BAMUMSUPPLEMENT */ + { 255, 2, 265}, /* BAMUMSUP */ + {1022, 2, 266}, /* MRO */ + {1383, 2, 267}, /* TANGSA */ + { 259, 2, 268}, /* BASSAVAH */ + {1159, 2, 269}, /* PAHAWHHMONG */ + { 820, 2, 270}, /* KIRATRAI */ + { 978, 2, 271}, /* MEDEFAIDRIN */ + { 991, 2, 272}, /* MIAO */ + { 734, 2, 273}, /* IDEOGRAPHICSYMBOLSANDPUNCTUATION */ + { 733, 2, 273}, /* IDEOGRAPHICSYMBOLS */ + {1384, 2, 274}, /* TANGUT */ + {1385, 2, 275}, /* TANGUTCOMPONENTS */ + { 813, 2, 276}, /* KHITANSMALLSCRIPT */ + {1387, 2, 277}, /* TANGUTSUPPLEMENT */ + {1386, 2, 277}, /* TANGUTSUP */ + { 794, 2, 278}, /* KANAEXTENDEDB */ + { 792, 2, 278}, /* KANAEXTB */ + { 796, 2, 279}, /* KANASUPPLEMENT */ + { 795, 2, 279}, /* KANASUP */ + { 793, 2, 280}, /* KANAEXTENDEDA */ + { 791, 2, 280}, /* KANAEXTA */ + {1295, 2, 281}, /* SMALLKANAEXTENSION */ + {1294, 2, 281}, /* SMALLKANAEXT */ + {1097, 2, 282}, /* NUSHU */ + { 541, 2, 283}, /* DUPLOYAN */ + {1279, 2, 284}, /* SHORTHANDFORMATCONTROLS */ + {1357, 2, 285}, /* SYMBOLSFORLEGACYCOMPUTINGSUPPLEMENT */ + {1356, 2, 285}, /* SYMBOLSFORLEGACYCOMPUTINGSUP */ + {1522, 2, 286}, /* ZNAMENNYMUSICALNOTATION */ + {1521, 2, 286}, /* ZNAMENNYMUSIC */ + { 312, 2, 287}, /* BYZANTINEMUSICALSYMBOLS */ + { 311, 2, 287}, /* BYZANTINEMUSIC */ + {1028, 2, 288}, /* MUSICALSYMBOLS */ + {1027, 2, 288}, /* MUSIC */ + { 203, 2, 289}, /* ANCIENTGREEKMUSICALNOTATION */ + { 202, 2, 289}, /* ANCIENTGREEKMUSIC */ + { 788, 2, 290}, /* KAKTOVIKNUMERALS */ + { 971, 2, 291}, /* MAYANNUMERALS */ + {1373, 2, 292}, /* TAIXUANJINGSYMBOLS */ + {1372, 2, 292}, /* TAIXUANJING */ + { 465, 2, 293}, /* COUNTINGRODNUMERALS */ + { 464, 2, 293}, /* COUNTINGROD */ + { 967, 2, 294}, /* MATHEMATICALALPHANUMERICSYMBOLS */ + { 966, 2, 294}, /* MATHALPHANUM */ + {1346, 2, 295}, /* SUTTONSIGNWRITING */ + { 851, 2, 296}, /* LATINEXTENDEDG */ + { 853, 2, 296}, /* LATINEXTG */ + { 644, 2, 297}, /* GLAGOLITICSUPPLEMENT */ + { 643, 2, 297}, /* GLAGOLITICSUP */ + { 492, 2, 298}, /* CYRILLICEXTENDEDD */ + { 488, 2, 298}, /* CYRILLICEXTD */ + {1100, 2, 299}, /* NYIAKENGPUACHUEHMONG */ + {1421, 2, 300}, /* TOTO */ + {1475, 2, 301}, /* WANCHO */ + {1042, 2, 302}, /* NAGMUNDARI */ + {1121, 2, 303}, /* OLONAL */ + { 590, 2, 304}, /* ETHIOPICEXTENDEDB */ + { 587, 2, 304}, /* ETHIOPICEXTB */ + { 986, 2, 305}, /* MENDEKIKAKUI */ + { 172, 2, 306}, /* ADLAM */ + { 749, 2, 307}, /* INDICSIYAQNUMBERS */ + {1151, 2, 308}, /* OTTOMANSIYAQNUMBERS */ + { 219, 2, 309}, /* ARABICMATHEMATICALALPHABETICSYMBOLS */ + { 218, 2, 309}, /* ARABICMATH */ + { 914, 2, 310}, /* MAHJONGTILES */ + { 913, 2, 310}, /* MAHJONG */ + { 532, 2, 311}, /* DOMINOTILES */ + { 531, 2, 311}, /* DOMINO */ + {1190, 2, 312}, /* PLAYINGCARDS */ + { 573, 2, 313}, /* ENCLOSEDALPHANUMERICSUPPLEMENT */ + { 574, 2, 313}, /* ENCLOSEDALPHANUMSUP */ + { 578, 2, 314}, /* ENCLOSEDIDEOGRAPHICSUPPLEMENT */ + { 577, 2, 314}, /* ENCLOSEDIDEOGRAPHICSUP */ + {1001, 2, 315}, /* MISCELLANEOUSSYMBOLSANDPICTOGRAPHS */ + {1005, 2, 315}, /* MISCPICTOGRAPHS */ + { 568, 2, 316}, /* EMOTICONS */ + {1131, 2, 317}, /* ORNAMENTALDINGBATS */ + {1425, 2, 318}, /* TRANSPORTANDMAPSYMBOLS */ + {1424, 2, 318}, /* TRANSPORTANDMAP */ + { 190, 2, 319}, /* ALCHEMICALSYMBOLS */ + { 189, 2, 319}, /* ALCHEMICAL */ + { 633, 2, 320}, /* GEOMETRICSHAPESEXTENDED */ + { 632, 2, 320}, /* GEOMETRICSHAPESEXT */ + {1335, 2, 321}, /* SUPPLEMENTALARROWSC */ + {1328, 2, 321}, /* SUPARROWSC */ + {1338, 2, 322}, /* SUPPLEMENTALSYMBOLSANDPICTOGRAPHS */ + {1344, 2, 322}, /* SUPSYMBOLSANDPICTOGRAPHS */ + { 382, 2, 323}, /* CHESSSYMBOLS */ + {1354, 2, 324}, /* SYMBOLSANDPICTOGRAPHSEXTENDEDA */ + {1353, 2, 324}, /* SYMBOLSANDPICTOGRAPHSEXTA */ + {1355, 2, 325}, /* SYMBOLSFORLEGACYCOMPUTING */ + { 413, 2, 326}, /* CJKUNIFIEDIDEOGRAPHSEXTENSIONB */ + { 398, 2, 326}, /* CJKEXTB */ + { 414, 2, 327}, /* CJKUNIFIEDIDEOGRAPHSEXTENSIONC */ + { 399, 2, 327}, /* CJKEXTC */ + { 415, 2, 328}, /* CJKUNIFIEDIDEOGRAPHSEXTENSIOND */ + { 400, 2, 328}, /* CJKEXTD */ + { 416, 2, 329}, /* CJKUNIFIEDIDEOGRAPHSEXTENSIONE */ + { 401, 2, 329}, /* CJKEXTE */ + { 417, 2, 330}, /* CJKUNIFIEDIDEOGRAPHSEXTENSIONF */ + { 402, 2, 330}, /* CJKEXTF */ + { 420, 2, 331}, /* CJKUNIFIEDIDEOGRAPHSEXTENSIONI */ + { 405, 2, 331}, /* CJKEXTI */ + { 394, 2, 332}, /* CJKCOMPATIBILITYIDEOGRAPHSSUPPLEMENT */ + { 396, 2, 332}, /* CJKCOMPATIDEOGRAPHSSUP */ + { 418, 2, 333}, /* CJKUNIFIEDIDEOGRAPHSEXTENSIONG */ + { 403, 2, 333}, /* CJKEXTG */ + { 419, 2, 334}, /* CJKUNIFIEDIDEOGRAPHSEXTENSIONH */ + { 404, 2, 334}, /* CJKEXTH */ + {1367, 2, 335}, /* TAGS */ + {1451, 2, 336}, /* VARIATIONSELECTORSSUPPLEMENT */ + {1473, 2, 336}, /* VSSUP */ + {1339, 2, 337}, /* SUPPLEMENTARYPRIVATEUSEAREAA */ + {1341, 2, 337}, /* SUPPUAA */ + {1340, 2, 338}, /* SUPPLEMENTARYPRIVATEUSEAREAB */ + {1342, 2, 338}, /* SUPPUAB */ + {1082, 3, 0}, /* NOTREORDERED */ + { 1, 3, 0}, /* 0 */ + {1083, 3, 0}, /* NR */ + { 169, 3, 1}, /* ABOVE */ + { 77, 3, 1}, /* 230 */ + { 168, 3, 1}, /* A */ + { 171, 3, 2}, /* ABOVERIGHT */ + { 78, 3, 2}, /* 232 */ + { 208, 3, 2}, /* AR */ + { 265, 3, 3}, /* BELOW */ + { 71, 3, 3}, /* 220 */ + { 248, 3, 3}, /* B */ + { 242, 3, 4}, /* ATTACHEDABOVERIGHT */ + { 67, 3, 4}, /* 216 */ + { 237, 3, 4}, /* ATAR */ + { 243, 3, 5}, /* ATTACHEDBELOW */ + { 64, 3, 5}, /* 202 */ + { 238, 3, 5}, /* ATB */ + {1155, 3, 6}, /* OVERLAY */ + { 2, 3, 6}, /* 1 */ + {1154, 3, 6}, /* OV */ + { 763, 3, 7}, /* IOTASUBSCRIPT */ + { 82, 3, 7}, /* 240 */ + { 766, 3, 7}, /* IS */ + { 534, 3, 8}, /* DOUBLEBELOW */ + { 79, 3, 8}, /* 233 */ + { 503, 3, 8}, /* DB */ + { 533, 3, 9}, /* DOUBLEABOVE */ + { 80, 3, 9}, /* 234 */ + { 498, 3, 9}, /* DA */ + { 267, 3, 10}, /* BELOWRIGHT */ + { 72, 3, 10}, /* 222 */ + { 295, 3, 10}, /* BR */ + { 170, 3, 11}, /* ABOVELEFT */ + { 75, 3, 11}, /* 228 */ + { 187, 3, 11}, /* AL */ + { 333, 3, 12}, /* CCC10 */ + { 21, 3, 12}, /* 10 */ + { 336, 3, 13}, /* CCC11 */ + { 35, 3, 13}, /* 11 */ + { 338, 3, 14}, /* CCC12 */ + { 39, 3, 14}, /* 12 */ + { 341, 3, 15}, /* CCC13 */ + { 42, 3, 15}, /* 13 */ + { 345, 3, 16}, /* CCC14 */ + { 47, 3, 16}, /* 14 */ + { 346, 3, 17}, /* CCC15 */ + { 48, 3, 17}, /* 15 */ + { 347, 3, 18}, /* CCC16 */ + { 50, 3, 18}, /* 16 */ + { 348, 3, 19}, /* CCC17 */ + { 51, 3, 19}, /* 17 */ + { 349, 3, 20}, /* CCC18 */ + { 53, 3, 20}, /* 18 */ + { 350, 3, 21}, /* CCC19 */ + { 54, 3, 21}, /* 19 */ + { 351, 3, 22}, /* CCC20 */ + { 58, 3, 22}, /* 20 */ + { 352, 3, 23}, /* CCC21 */ + { 65, 3, 23}, /* 21 */ + { 353, 3, 24}, /* CCC22 */ + { 70, 3, 24}, /* 22 */ + { 354, 3, 25}, /* CCC23 */ + { 76, 3, 25}, /* 23 */ + { 355, 3, 26}, /* CCC24 */ + { 81, 3, 26}, /* 24 */ + { 356, 3, 27}, /* CCC25 */ + { 83, 3, 27}, /* 25 */ + { 361, 3, 28}, /* CCC30 */ + { 97, 3, 28}, /* 30 */ + { 362, 3, 29}, /* CCC31 */ + { 102, 3, 29}, /* 31 */ + { 363, 3, 30}, /* CCC32 */ + { 103, 3, 30}, /* 32 */ + { 358, 3, 31}, /* CCC27 */ + { 85, 3, 31}, /* 27 */ + { 359, 3, 32}, /* CCC28 */ + { 86, 3, 32}, /* 28 */ + { 360, 3, 33}, /* CCC29 */ + { 87, 3, 33}, /* 29 */ + { 364, 3, 34}, /* CCC33 */ + { 104, 3, 34}, /* 33 */ + { 365, 3, 35}, /* CCC34 */ + { 105, 3, 35}, /* 34 */ + { 366, 3, 36}, /* CCC35 */ + { 106, 3, 36}, /* 35 */ + { 367, 3, 37}, /* CCC36 */ + { 107, 3, 37}, /* 36 */ + {1089, 3, 38}, /* NUKTA */ + { 144, 3, 38}, /* 7 */ + {1066, 3, 38}, /* NK */ + {1461, 3, 39}, /* VIRAMA */ + { 160, 3, 39}, /* 9 */ + {1471, 3, 39}, /* VR */ + { 368, 3, 40}, /* CCC84 */ + { 159, 3, 40}, /* 84 */ + { 369, 3, 41}, /* CCC91 */ + { 167, 3, 41}, /* 91 */ + { 334, 3, 42}, /* CCC103 */ + { 33, 3, 42}, /* 103 */ + { 335, 3, 43}, /* CCC107 */ + { 34, 3, 43}, /* 107 */ + { 337, 3, 44}, /* CCC118 */ + { 38, 3, 44}, /* 118 */ + { 339, 3, 45}, /* CCC122 */ + { 40, 3, 45}, /* 122 */ + { 340, 3, 46}, /* CCC129 */ + { 41, 3, 46}, /* 129 */ + { 342, 3, 47}, /* CCC130 */ + { 44, 3, 47}, /* 130 */ + { 343, 3, 48}, /* CCC132 */ + { 45, 3, 48}, /* 132 */ + { 241, 3, 49}, /* ATTACHEDABOVE */ + { 66, 3, 49}, /* 214 */ + { 236, 3, 49}, /* ATA */ + { 266, 3, 50}, /* BELOWLEFT */ + { 69, 3, 50}, /* 218 */ + { 280, 3, 50}, /* BL */ + { 859, 3, 51}, /* LEFT */ + { 73, 3, 51}, /* 224 */ + { 827, 3, 51}, /* L */ + { 797, 3, 52}, /* KANAVOICING */ + { 153, 3, 52}, /* 8 */ + { 826, 3, 52}, /* KV */ + { 357, 3, 53}, /* CCC26 */ + { 84, 3, 53}, /* 26 */ + { 697, 3, 54}, /* HANREADING */ + { 138, 3, 54}, /* 6 */ + { 696, 3, 54}, /* HANR */ + {1232, 3, 55}, /* RIGHT */ + { 74, 3, 55}, /* 226 */ + {1223, 3, 55}, /* R */ + { 344, 3, 56}, /* CCC133 */ + { 46, 3, 56}, /* 133 */ + { 244, 3, 57}, /* ATTACHEDBELOWLEFT */ + { 59, 3, 57}, /* 200 */ + { 239, 3, 57}, /* ATBL */ + {1075, 4, 0}, /* NONE */ + {1072, 4, 1}, /* NOBREAK */ + {1049, 4, 1}, /* NB */ + { 440, 4, 2}, /* COMPAT */ + { 429, 4, 2}, /* COM */ + {1329, 4, 3}, /* SUPER */ + {1325, 4, 3}, /* SUP */ + { 618, 4, 4}, /* FRACTION */ + { 617, 4, 4}, /* FRA */ + { 319, 4, 5}, /* CANONICAL */ + { 316, 4, 5}, /* CAN */ + {1318, 4, 6}, /* SUB */ + { 615, 4, 7}, /* FONT */ + { 386, 4, 8}, /* CIRCLE */ + { 570, 4, 8}, /* ENC */ + {1482, 4, 9}, /* WIDE */ + {1455, 4, 10}, /* VERTICAL */ + {1454, 4, 10}, /* VERT */ + {1314, 4, 11}, /* SQUARE */ + {1313, 4, 11}, /* SQR */ + { 768, 4, 12}, /* ISOLATED */ + { 767, 4, 12}, /* ISO */ + { 610, 4, 13}, /* FINAL */ + { 609, 4, 13}, /* FIN */ + { 754, 4, 14}, /* INITIAL */ + { 753, 4, 14}, /* INIT */ + { 980, 4, 15}, /* MEDIAL */ + { 977, 4, 15}, /* MED */ + {1291, 4, 16}, /* SMALL */ + {1296, 4, 16}, /* SML */ + {1048, 4, 17}, /* NARROW */ + {1046, 4, 17}, /* NAR */ + {1482, 5, 0}, /* WIDE */ + {1474, 5, 0}, /* W */ + {1053, 5, 1}, /* NEUTRAL */ + {1037, 5, 1}, /* N */ + {1048, 5, 2}, /* NARROW */ + {1039, 5, 2}, /* NA */ + { 199, 5, 3}, /* AMBIGUOUS */ + { 168, 5, 3}, /* A */ + { 679, 5, 4}, /* HALFWIDTH */ + { 673, 5, 4}, /* H */ + { 620, 5, 5}, /* FULLWIDTH */ + { 604, 5, 5}, /* F */ + {1436, 6, 0}, /* UNASSIGNED */ + { 426, 6, 0}, /* CN */ + { 459, 6, 1}, /* CONTROL */ + { 331, 6, 1}, /* CC */ + { 427, 6, 1}, /* CNTRL */ + {1308, 6, 2}, /* SPACESEPARATOR */ + {1524, 6, 2}, /* ZS */ + {1148, 6, 3}, /* OTHERPUNCTUATION */ + {1192, 6, 3}, /* PO */ + { 474, 6, 4}, /* CURRENCYSYMBOL */ + {1259, 6, 4}, /* SC */ + {1127, 6, 5}, /* OPENPUNCTUATION */ + {1209, 6, 5}, /* PS */ + { 424, 6, 6}, /* CLOSEPUNCTUATION */ + {1174, 6, 6}, /* PE */ + { 970, 6, 7}, /* MATHSYMBOL */ + {1290, 6, 7}, /* SM */ + { 502, 6, 8}, /* DASHPUNCTUATION */ + {1171, 6, 8}, /* PD */ + { 506, 6, 9}, /* DECIMALNUMBER */ + {1052, 6, 9}, /* ND */ + { 526, 6, 9}, /* DIGIT */ + {1445, 6, 10}, /* UPPERCASELETTER */ + { 900, 6, 10}, /* LU */ + {1015, 6, 11}, /* MODIFIERSYMBOL */ + {1289, 6, 11}, /* SK */ + { 444, 6, 12}, /* CONNECTORPUNCTUATION */ + {1169, 6, 12}, /* PC */ + { 894, 6, 13}, /* LOWERCASELETTER */ + { 887, 6, 13}, /* LL */ + {1149, 6, 14}, /* OTHERSYMBOL */ + {1297, 6, 14}, /* SO */ + {1143, 6, 15}, /* OTHERLETTER */ + { 889, 6, 15}, /* LO */ + { 755, 6, 16}, /* INITIALPUNCTUATION */ + {1189, 6, 16}, /* PI */ + { 616, 6, 17}, /* FORMAT */ + { 370, 6, 17}, /* CF */ + {1147, 6, 18}, /* OTHERNUMBER */ + {1070, 6, 18}, /* NO */ + { 611, 6, 19}, /* FINALPUNCTUATION */ + {1176, 6, 19}, /* PF */ + {1408, 6, 20}, /* TITLECASELETTER */ + { 899, 6, 20}, /* LT */ + {1013, 6, 21}, /* MODIFIERLETTER */ + { 888, 6, 21}, /* LM */ + {1078, 6, 22}, /* NONSPACINGMARK */ + {1010, 6, 22}, /* MN */ + { 579, 6, 23}, /* ENCLOSINGMARK */ + { 976, 6, 23}, /* ME */ + {1309, 6, 24}, /* SPACINGMARK */ + { 974, 6, 24}, /* MC */ + { 870, 6, 25}, /* LETTERNUMBER */ + {1069, 6, 25}, /* NL */ + { 882, 6, 26}, /* LINESEPARATOR */ + {1520, 6, 26}, /* ZL */ + {1162, 6, 27}, /* PARAGRAPHSEPARATOR */ + {1523, 6, 27}, /* ZP */ + {1345, 6, 28}, /* SURROGATE */ + { 470, 6, 28}, /* CS */ + {1206, 6, 29}, /* PRIVATEUSE */ + { 428, 6, 29}, /* CO */ + {1137, 6, 30}, /* OTHER */ + { 313, 6, 30}, /* C */ + { 314, 6, 30}, /* C& */ + { 868, 6, 31}, /* LETTER */ + { 827, 6, 31}, /* L */ + { 828, 6, 31}, /* L& */ + { 963, 6, 32}, /* MARK */ + { 909, 6, 32}, /* M */ + { 435, 6, 32}, /* COMBININGMARK */ + { 910, 6, 32}, /* M& */ + {1090, 6, 33}, /* NUMBER */ + {1037, 6, 33}, /* N */ + {1038, 6, 33}, /* N& */ + {1213, 6, 34}, /* PUNCTUATION */ + {1157, 6, 34}, /* P */ + {1212, 6, 34}, /* PUNCT */ + {1158, 6, 34}, /* P& */ + {1352, 6, 35}, /* SYMBOL */ + {1248, 6, 35}, /* S */ + {1249, 6, 35}, /* S& */ + {1272, 6, 36}, /* SEPARATOR */ + {1513, 6, 36}, /* Z */ + {1514, 6, 36}, /* Z& */ + { 234, 6, 37}, /* ASSIGNED */ + { 327, 6, 38}, /* CASEDLETTER */ + { 856, 6, 38}, /* LC */ + {1137, 7, 0}, /* OTHER */ + {1497, 7, 0}, /* XX */ + { 459, 7, 1}, /* CONTROL */ + { 426, 7, 1}, /* CN */ + { 871, 7, 2}, /* LF */ + { 469, 7, 3}, /* CR */ + { 599, 7, 4}, /* EXTEND */ + { 596, 7, 4}, /* EX */ + {1203, 7, 5}, /* PREPEND */ + {1200, 7, 5}, /* PP */ + {1309, 7, 6}, /* SPACINGMARK */ + {1290, 7, 6}, /* SM */ + { 827, 7, 7}, /* L */ + {1446, 7, 8}, /* V */ + {1363, 7, 9}, /* T */ + {1526, 7, 10}, /* ZWJ */ + { 901, 7, 11}, /* LV */ + { 903, 7, 12}, /* LVT */ + {1225, 7, 13}, /* REGIONALINDICATOR */ + {1231, 7, 13}, /* RI */ + { 547, 7, 14}, /* EBASE */ + { 546, 7, 14}, /* EB */ + { 548, 7, 15}, /* EBASEGAZ */ + { 549, 7, 15}, /* EBG */ + { 562, 7, 16}, /* EMODIFIER */ + { 560, 7, 16}, /* EM */ + { 646, 7, 17}, /* GLUEAFTERZWJ */ + { 625, 7, 17}, /* GAZ */ + {1081, 8, 0}, /* NOTAPPLICABLE */ + {1039, 8, 0}, /* NA */ + { 858, 8, 1}, /* LEADINGJAMO */ + { 827, 8, 1}, /* L */ + {1470, 8, 2}, /* VOWELJAMO */ + {1446, 8, 2}, /* V */ + {1422, 8, 3}, /* TRAILINGJAMO */ + {1363, 8, 3}, /* T */ + { 902, 8, 4}, /* LVSYLLABLE */ + { 901, 8, 4}, /* LV */ + { 904, 8, 5}, /* LVTSYLLABLE */ + { 903, 8, 5}, /* LVT */ + {1075, 9, 0}, /* NONE */ + { 599, 9, 1}, /* EXTEND */ + { 445, 9, 2}, /* CONSONANT */ + { 883, 9, 3}, /* LINKER */ + {1039, 10, 0}, /* NA */ + {1414, 10, 1}, /* TOP */ + {1232, 10, 2}, /* RIGHT */ + { 290, 10, 3}, /* BOTTOM */ + { 859, 10, 4}, /* LEFT */ + { 860, 10, 5}, /* LEFTANDRIGHT */ + {1420, 10, 6}, /* TOPANDRIGHT */ + {1418, 10, 7}, /* TOPANDLEFT */ + {1419, 10, 8}, /* TOPANDLEFTANDRIGHT */ + {1415, 10, 9}, /* TOPANDBOTTOM */ + {1464, 10, 10}, /* VISUALORDERLEFT */ + {1416, 10, 11}, /* TOPANDBOTTOMANDLEFT */ + { 292, 10, 12}, /* BOTTOMANDRIGHT */ + {1417, 10, 13}, /* TOPANDBOTTOMANDRIGHT */ + {1156, 10, 14}, /* OVERSTRUCK */ + { 291, 10, 15}, /* BOTTOMANDLEFT */ + {1137, 11, 0}, /* OTHER */ + { 452, 11, 1}, /* CONSONANTPLACEHOLDER */ + {1090, 11, 2}, /* NUMBER */ + {1349, 11, 3}, /* SYLLABLEMODIFIER */ + { 278, 11, 4}, /* BINDU */ + {1463, 11, 5}, /* VISARGA */ + {1469, 11, 6}, /* VOWELINDEPENDENT */ + { 445, 11, 7}, /* CONSONANT */ + {1468, 11, 8}, /* VOWELDEPENDENT */ + {1089, 11, 9}, /* NUKTA */ + { 245, 11, 10}, /* AVAGRAHA */ + {1461, 11, 11}, /* VIRAMA */ + { 322, 11, 12}, /* CANTILLATIONMARK */ + { 446, 11, 13}, /* CONSONANTDEAD */ + { 628, 11, 14}, /* GEMINATIONMARK */ + { 451, 11, 15}, /* CONSONANTMEDIAL */ + {1017, 11, 16}, /* MODIFYINGLETTER */ + { 457, 11, 17}, /* CONSONANTWITHSTACKER */ + {1214, 11, 18}, /* PUREKILLER */ + { 453, 11, 19}, /* CONSONANTPRECEDINGREPHA */ + {1413, 11, 20}, /* TONEMARK */ + { 450, 11, 21}, /* CONSONANTKILLER */ + { 448, 11, 22}, /* CONSONANTHEADLETTER */ + { 455, 11, 23}, /* CONSONANTSUBJOINED */ + { 762, 11, 24}, /* INVISIBLESTACKER */ + {1226, 11, 25}, /* REGISTERSHIFTER */ + { 456, 11, 26}, /* CONSONANTSUCCEEDINGREPHA */ + { 447, 11, 27}, /* CONSONANTFINAL */ + {1467, 11, 28}, /* VOWEL */ + {1412, 11, 29}, /* TONELETTER */ + { 449, 11, 30}, /* CONSONANTINITIALPOSTFIXED */ + {1229, 11, 31}, /* REORDERINGKILLER */ + {1076, 11, 32}, /* NONJOINER */ + { 780, 11, 33}, /* JOINER */ + { 298, 11, 34}, /* BRAHMIJOININGNUMBER */ + {1092, 11, 35}, /* NUMBERJOINER */ + { 454, 11, 36}, /* CONSONANTPREFIXED */ + {1073, 12, 0}, /* NOJOININGGROUP */ + { 803, 12, 1}, /* KASHMIRIYEH */ + { 191, 12, 2}, /* ALEF */ + {1478, 12, 3}, /* WAW */ + {1499, 12, 4}, /* YEH */ + { 264, 12, 5}, /* BEH */ + {1390, 12, 6}, /* TEHMARBUTA */ + { 676, 12, 7}, /* HAH */ + { 499, 12, 8}, /* DAL */ + {1227, 12, 9}, /* REH */ + {1266, 12, 10}, /* SEEN */ + {1251, 12, 11}, /* SAD */ + {1368, 12, 12}, /* TAH */ + { 182, 12, 13}, /* AIN */ + { 621, 12, 14}, /* GAF */ + { 606, 12, 15}, /* FARSIYEH */ + { 608, 12, 16}, /* FEH */ + {1217, 12, 17}, /* QAF */ + { 786, 12, 18}, /* KAF */ + { 829, 12, 19}, /* LAM */ + { 981, 12, 20}, /* MEEM */ + {1080, 12, 21}, /* NOON */ + { 705, 12, 22}, /* HEH */ + {1347, 12, 23}, /* SWASHKAF */ + {1099, 12, 24}, /* NYA */ + { 823, 12, 25}, /* KNOTTEDHEH */ + { 706, 12, 26}, /* HEHGOAL */ + {1391, 12, 27}, /* TEHMARBUTAGOAL */ + { 681, 12, 27}, /* HAMZAONHEHGOAL */ + {1501, 12, 28}, /* YEHWITHTAIL */ + {1500, 12, 29}, /* YEHBARREE */ + { 188, 12, 30}, /* ALAPH */ + { 270, 12, 31}, /* BETH */ + { 622, 12, 32}, /* GAMAL */ + { 500, 12, 33}, /* DALATHRISH */ + { 701, 12, 34}, /* HE */ + {1362, 12, 35}, /* SYRIACWAW */ + {1515, 12, 36}, /* ZAIN */ + { 707, 12, 37}, /* HETH */ + {1396, 12, 38}, /* TETH */ + {1511, 12, 39}, /* YUDH */ + {1512, 12, 40}, /* YUDHHE */ + { 802, 12, 41}, /* KAPH */ + { 830, 12, 42}, /* LAMADH */ + { 995, 12, 43}, /* MIM */ + {1096, 12, 44}, /* NUN */ + {1268, 12, 45}, /* SEMKATH */ + { 612, 12, 46}, /* FINALSEMKATH */ + { 542, 12, 47}, /* E */ + {1174, 12, 48}, /* PE */ + {1230, 12, 49}, /* REVERSEDPE */ + {1252, 12, 50}, /* SADHE */ + {1218, 12, 51}, /* QAPH */ + {1278, 12, 52}, /* SHIN */ + {1389, 12, 53}, /* TAW */ + {1518, 12, 54}, /* ZHAIN */ + { 810, 12, 55}, /* KHAPH */ + { 607, 12, 56}, /* FE */ + { 310, 12, 57}, /* BURUSHASKIYEHBARREE */ + { 922, 12, 58}, /* MALAYALAMNGA */ + { 919, 12, 59}, /* MALAYALAMJA */ + { 925, 12, 60}, /* MALAYALAMNYA */ + { 928, 12, 61}, /* MALAYALAMTTA */ + { 923, 12, 62}, /* MALAYALAMNNA */ + { 924, 12, 63}, /* MALAYALAMNNNA */ + { 918, 12, 64}, /* MALAYALAMBHA */ + { 926, 12, 65}, /* MALAYALAMRA */ + { 920, 12, 66}, /* MALAYALAMLLA */ + { 921, 12, 67}, /* MALAYALAMLLLA */ + { 927, 12, 68}, /* MALAYALAMSSA */ + {1402, 12, 69}, /* THINYEH */ + {1457, 12, 70}, /* VERTICALTAIL */ + {1243, 12, 71}, /* ROHINGYAYEH */ + {1317, 12, 72}, /* STRAIGHTWAW */ + { 175, 12, 73}, /* AFRICANFEH */ + { 177, 12, 74}, /* AFRICANQAF */ + { 176, 12, 75}, /* AFRICANNOON */ + { 934, 12, 76}, /* MANICHAEANALEPH */ + { 936, 12, 77}, /* MANICHAEANBETH */ + { 940, 12, 78}, /* MANICHAEANGIMEL */ + { 937, 12, 79}, /* MANICHAEANDALETH */ + { 958, 12, 80}, /* MANICHAEANWAW */ + { 960, 12, 81}, /* MANICHAEANZAYIN */ + { 941, 12, 82}, /* MANICHAEANHETH */ + { 955, 12, 83}, /* MANICHAEANTETH */ + { 959, 12, 84}, /* MANICHAEANYODH */ + { 943, 12, 85}, /* MANICHAEANKAPH */ + { 944, 12, 86}, /* MANICHAEANLAMEDH */ + { 938, 12, 87}, /* MANICHAEANDHAMEDH */ + { 956, 12, 88}, /* MANICHAEANTHAMEDH */ + { 945, 12, 89}, /* MANICHAEANMEM */ + { 946, 12, 90}, /* MANICHAEANNUN */ + { 952, 12, 91}, /* MANICHAEANSAMEKH */ + { 935, 12, 92}, /* MANICHAEANAYIN */ + { 948, 12, 93}, /* MANICHAEANPE */ + { 951, 12, 94}, /* MANICHAEANSADHE */ + { 949, 12, 95}, /* MANICHAEANQOPH */ + { 950, 12, 96}, /* MANICHAEANRESH */ + { 953, 12, 97}, /* MANICHAEANTAW */ + { 947, 12, 98}, /* MANICHAEANONE */ + { 939, 12, 99}, /* MANICHAEANFIVE */ + { 954, 12, 100}, /* MANICHAEANTEN */ + { 957, 12, 101}, /* MANICHAEANTWENTY */ + { 942, 12, 102}, /* MANICHAEANHUNDRED */ + { 694, 12, 103}, /* HANIFIROHINGYAPA */ + { 693, 12, 104}, /* HANIFIROHINGYAKINNAYA */ + {1077, 13, 0}, /* NONJOINING */ + {1429, 13, 0}, /* U */ + {1423, 13, 1}, /* TRANSPARENT */ + {1363, 13, 1}, /* T */ + { 539, 13, 2}, /* DUALJOINING */ + { 497, 13, 2}, /* D */ + {1233, 13, 3}, /* RIGHTJOINING */ + {1223, 13, 3}, /* R */ + { 778, 13, 4}, /* JOINCAUSING */ + { 313, 13, 4}, /* C */ + { 861, 13, 5}, /* LEFTJOINING */ + { 827, 13, 5}, /* L */ + {1441, 14, 0}, /* UNKNOWN */ + {1497, 14, 0}, /* XX */ + { 435, 14, 1}, /* COMBININGMARK */ + { 425, 14, 1}, /* CM */ + { 302, 14, 2}, /* BREAKAFTER */ + { 250, 14, 2}, /* BA */ + { 881, 14, 3}, /* LINEFEED */ + { 871, 14, 3}, /* LF */ + { 931, 14, 4}, /* MANDATORYBREAK */ + { 279, 14, 4}, /* BK */ + { 325, 14, 5}, /* CARRIAGERETURN */ + { 469, 14, 5}, /* CR */ + {1307, 14, 6}, /* SPACE */ + {1306, 14, 6}, /* SP */ + { 597, 14, 7}, /* EXCLAMATION */ + { 596, 14, 7}, /* EX */ + {1221, 14, 8}, /* QUOTATION */ + {1220, 14, 8}, /* QU */ + { 195, 14, 9}, /* ALPHABETIC */ + { 187, 14, 9}, /* AL */ + {1202, 14, 10}, /* PREFIXNUMERIC */ + {1201, 14, 10}, /* PR */ + {1199, 14, 11}, /* POSTFIXNUMERIC */ + {1192, 14, 11}, /* PO */ + {1127, 14, 12}, /* OPENPUNCTUATION */ + {1126, 14, 12}, /* OP */ + { 423, 14, 13}, /* CLOSEPARENTHESIS */ + { 466, 14, 13}, /* CP */ + { 751, 14, 14}, /* INFIXNUMERIC */ + { 766, 14, 14}, /* IS */ + { 724, 14, 15}, /* HYPHEN */ + { 723, 14, 15}, /* HY */ + { 305, 14, 16}, /* BREAKSYMBOLS */ + {1348, 14, 16}, /* SY */ + {1093, 14, 17}, /* NUMERIC */ + {1088, 14, 17}, /* NU */ + { 424, 14, 18}, /* CLOSEPUNCTUATION */ + { 421, 14, 18}, /* CL */ + {1057, 14, 19}, /* NEXTLINE */ + {1069, 14, 19}, /* NL */ + { 645, 14, 20}, /* GLUE */ + { 640, 14, 20}, /* GL */ + { 199, 14, 21}, /* AMBIGUOUS */ + { 181, 14, 21}, /* AI */ + { 303, 14, 22}, /* BREAKBEFORE */ + { 262, 14, 22}, /* BB */ + { 704, 14, 23}, /* HEBREWLETTER */ + { 715, 14, 23}, /* HL */ + { 442, 14, 24}, /* COMPLEXCONTEXT */ + {1250, 14, 24}, /* SA */ + { 776, 14, 25}, /* JL */ + { 784, 14, 26}, /* JV */ + { 783, 14, 27}, /* JT */ + {1079, 14, 28}, /* NONSTARTER */ + {1084, 14, 28}, /* NS */ + { 184, 14, 29}, /* AKSARA */ + { 183, 14, 29}, /* AK */ + {1461, 14, 30}, /* VIRAMA */ + {1460, 14, 30}, /* VI */ + { 186, 14, 31}, /* AKSARASTART */ + { 231, 14, 31}, /* AS */ + { 731, 14, 32}, /* IDEOGRAPHIC */ + { 725, 14, 32}, /* ID */ + {1462, 14, 33}, /* VIRAMAFINAL */ + {1459, 14, 33}, /* VF */ + {1527, 14, 34}, /* ZWSPACE */ + {1525, 14, 34}, /* ZW */ + {1526, 14, 35}, /* ZWJ */ + { 304, 14, 36}, /* BREAKBOTH */ + { 249, 14, 36}, /* B2 */ + { 760, 14, 37}, /* INSEPARABLE */ + { 744, 14, 37}, /* IN */ + { 761, 14, 37}, /* INSEPERABLE */ + {1486, 14, 38}, /* WORDJOINER */ + {1483, 14, 38}, /* WJ */ + { 547, 14, 39}, /* EBASE */ + { 546, 14, 39}, /* EB */ + { 443, 14, 40}, /* CONDITIONALJAPANESESTARTER */ + { 387, 14, 40}, /* CJ */ + { 674, 14, 41}, /* H2 */ + { 675, 14, 42}, /* H3 */ + {1345, 14, 43}, /* SURROGATE */ + {1273, 14, 43}, /* SG */ + { 458, 14, 44}, /* CONTINGENTBREAK */ + { 330, 14, 44}, /* CB */ + { 185, 14, 45}, /* AKSARAPREBASE */ + { 207, 14, 45}, /* AP */ + {1225, 14, 46}, /* REGIONALINDICATOR */ + {1231, 14, 46}, /* RI */ + { 562, 14, 47}, /* EMODIFIER */ + { 560, 14, 47}, /* EM */ + {1070, 15, 0}, /* NO */ + {1037, 15, 0}, /* N */ + {1502, 15, 1}, /* YES */ + {1498, 15, 1}, /* Y */ + { 972, 15, 2}, /* MAYBE */ + { 909, 15, 2}, /* M */ + {1070, 16, 0}, /* NO */ + {1037, 16, 0}, /* N */ + {1502, 16, 1}, /* YES */ + {1498, 16, 1}, /* Y */ + {1075, 17, 0}, /* NONE */ + { 505, 17, 1}, /* DECIMAL */ + { 504, 17, 1}, /* DE */ + { 526, 17, 2}, /* DIGIT */ + { 518, 17, 2}, /* DI */ + {1093, 17, 3}, /* NUMERIC */ + {1088, 17, 3}, /* NU */ + {1043, 18, 0}, /* NAN */ + { 1, 18, 1}, /* 0 */ + { 2, 18, 2}, /* 1 */ + { 55, 18, 3}, /* 2 */ + { 88, 18, 4}, /* 3 */ + { 111, 18, 5}, /* 4 */ + { 128, 18, 6}, /* 5 */ + { 138, 18, 7}, /* 6 */ + { 144, 18, 8}, /* 7 */ + { 153, 18, 9}, /* 8 */ + { 160, 18, 10}, /* 9 */ + { 12, 18, 11}, /* 1/4 */ + { 7, 18, 12}, /* 1/2 */ + { 92, 18, 13}, /* 3/4 */ + { 5, 18, 14}, /* 1/16 */ + { 18, 18, 15}, /* 1/8 */ + { 89, 18, 16}, /* 3/16 */ + { 50, 18, 17}, /* 16 */ + { 21, 18, 18}, /* 10 */ + { 22, 18, 19}, /* 100 */ + { 23, 18, 20}, /* 1000 */ + { 6, 18, 21}, /* 1/160 */ + { 13, 18, 22}, /* 1/40 */ + { 96, 18, 23}, /* 3/80 */ + { 8, 18, 24}, /* 1/20 */ + { 3, 18, 25}, /* 1/10 */ + { 91, 18, 26}, /* 3/20 */ + { 14, 18, 27}, /* 1/5 */ + { 90, 18, 28}, /* 3/2 */ + { 130, 18, 29}, /* 5/2 */ + { 146, 18, 30}, /* 7/2 */ + { 161, 18, 31}, /* 9/2 */ + { 37, 18, 32}, /* 11/2 */ + { 43, 18, 33}, /* 13/2 */ + { 49, 18, 34}, /* 15/2 */ + { 52, 18, 35}, /* 17/2 */ + { 0, 18, 36}, /* -1/2 */ + { 58, 18, 37}, /* 20 */ + { 97, 18, 38}, /* 30 */ + { 113, 18, 39}, /* 40 */ + { 133, 18, 40}, /* 50 */ + { 139, 18, 41}, /* 60 */ + { 148, 18, 42}, /* 70 */ + { 154, 18, 43}, /* 80 */ + { 162, 18, 44}, /* 90 */ + { 24, 18, 45}, /* 10000 */ + { 51, 18, 46}, /* 17 */ + { 53, 18, 47}, /* 18 */ + { 54, 18, 48}, /* 19 */ + { 17, 18, 49}, /* 1/7 */ + { 20, 18, 50}, /* 1/9 */ + { 9, 18, 51}, /* 1/3 */ + { 56, 18, 52}, /* 2/3 */ + { 57, 18, 53}, /* 2/5 */ + { 93, 18, 54}, /* 3/5 */ + { 112, 18, 55}, /* 4/5 */ + { 15, 18, 56}, /* 1/6 */ + { 131, 18, 57}, /* 5/6 */ + { 95, 18, 58}, /* 3/8 */ + { 132, 18, 59}, /* 5/8 */ + { 147, 18, 60}, /* 7/8 */ + { 35, 18, 61}, /* 11 */ + { 39, 18, 62}, /* 12 */ + { 134, 18, 63}, /* 500 */ + { 135, 18, 64}, /* 5000 */ + { 136, 18, 65}, /* 50000 */ + { 25, 18, 66}, /* 100000 */ + { 42, 18, 67}, /* 13 */ + { 47, 18, 68}, /* 14 */ + { 48, 18, 69}, /* 15 */ + { 65, 18, 70}, /* 21 */ + { 70, 18, 71}, /* 22 */ + { 76, 18, 72}, /* 23 */ + { 81, 18, 73}, /* 24 */ + { 83, 18, 74}, /* 25 */ + { 84, 18, 75}, /* 26 */ + { 85, 18, 76}, /* 27 */ + { 86, 18, 77}, /* 28 */ + { 87, 18, 78}, /* 29 */ + { 102, 18, 79}, /* 31 */ + { 103, 18, 80}, /* 32 */ + { 104, 18, 81}, /* 33 */ + { 105, 18, 82}, /* 34 */ + { 106, 18, 83}, /* 35 */ + { 107, 18, 84}, /* 36 */ + { 108, 18, 85}, /* 37 */ + { 109, 18, 86}, /* 38 */ + { 110, 18, 87}, /* 39 */ + { 118, 18, 88}, /* 41 */ + { 119, 18, 89}, /* 42 */ + { 120, 18, 90}, /* 43 */ + { 122, 18, 91}, /* 44 */ + { 123, 18, 92}, /* 45 */ + { 124, 18, 93}, /* 46 */ + { 125, 18, 94}, /* 47 */ + { 126, 18, 95}, /* 48 */ + { 127, 18, 96}, /* 49 */ + { 32, 18, 97}, /* 10000000000000000 */ + { 28, 18, 98}, /* 100000000 */ + { 26, 18, 99}, /* 1000000 */ + { 59, 18, 100}, /* 200 */ + { 29, 18, 101}, /* 1000000000 */ + { 98, 18, 102}, /* 300 */ + { 114, 18, 103}, /* 400 */ + { 140, 18, 104}, /* 600 */ + { 149, 18, 105}, /* 700 */ + { 155, 18, 106}, /* 800 */ + { 163, 18, 107}, /* 900 */ + { 60, 18, 108}, /* 2000 */ + { 99, 18, 109}, /* 3000 */ + { 115, 18, 110}, /* 4000 */ + { 141, 18, 111}, /* 6000 */ + { 150, 18, 112}, /* 7000 */ + { 156, 18, 113}, /* 8000 */ + { 164, 18, 114}, /* 9000 */ + { 61, 18, 115}, /* 20000 */ + { 100, 18, 116}, /* 30000 */ + { 116, 18, 117}, /* 40000 */ + { 142, 18, 118}, /* 60000 */ + { 151, 18, 119}, /* 70000 */ + { 157, 18, 120}, /* 80000 */ + { 165, 18, 121}, /* 90000 */ + { 36, 18, 122}, /* 11/12 */ + { 62, 18, 123}, /* 200000 */ + { 101, 18, 124}, /* 300000 */ + { 117, 18, 125}, /* 400000 */ + { 137, 18, 126}, /* 500000 */ + { 143, 18, 127}, /* 600000 */ + { 152, 18, 128}, /* 700000 */ + { 158, 18, 129}, /* 800000 */ + { 166, 18, 130}, /* 900000 */ + { 4, 18, 131}, /* 1/12 */ + { 129, 18, 132}, /* 5/12 */ + { 145, 18, 133}, /* 7/12 */ + { 11, 18, 134}, /* 1/320 */ + { 19, 18, 135}, /* 1/80 */ + { 16, 18, 136}, /* 1/64 */ + { 10, 18, 137}, /* 1/32 */ + { 94, 18, 138}, /* 3/64 */ + { 68, 18, 139}, /* 216000 */ + { 121, 18, 140}, /* 432000 */ + { 30, 18, 141}, /* 10000000000 */ + { 31, 18, 142}, /* 1000000000000 */ + { 27, 18, 143}, /* 10000000 */ + { 63, 18, 144}, /* 20000000 */ + {1441, 19, 0}, /* UNKNOWN */ + {1529, 19, 0}, /* ZZZZ */ + { 437, 19, 1}, /* COMMON */ + {1528, 19, 1}, /* ZYYY */ + { 834, 19, 2}, /* LATIN */ + { 854, 19, 2}, /* LATN */ + { 287, 19, 3}, /* BOPOMOFO */ + { 286, 19, 3}, /* BOPO */ + { 752, 19, 4}, /* INHERITED */ + {1519, 19, 4}, /* ZINH */ + {1216, 19, 4}, /* QAAI */ + { 659, 19, 5}, /* GREEK */ + { 663, 19, 5}, /* GREK */ + { 462, 19, 6}, /* COPTIC */ + { 461, 19, 6}, /* COPT */ + {1215, 19, 6}, /* QAAC */ + { 484, 19, 7}, /* CYRILLIC */ + { 496, 19, 7}, /* CYRL */ + { 227, 19, 8}, /* ARMENIAN */ + { 229, 19, 8}, /* ARMN */ + { 703, 19, 9}, /* HEBREW */ + { 702, 19, 9}, /* HEBR */ + { 210, 19, 10}, /* ARABIC */ + { 209, 19, 10}, /* ARAB */ + {1359, 19, 11}, /* SYRIAC */ + {1358, 19, 11}, /* SYRC */ + {1400, 19, 12}, /* THAANA */ + {1399, 19, 12}, /* THAA */ + {1067, 19, 13}, /* NKO */ + {1068, 19, 13}, /* NKOO */ + {1253, 19, 14}, /* SAMARITAN */ + {1254, 19, 14}, /* SAMR */ + { 930, 19, 15}, /* MANDAIC */ + { 929, 19, 15}, /* MAND */ + { 513, 19, 16}, /* DEVANAGARI */ + { 512, 19, 16}, /* DEVA */ + { 269, 19, 17}, /* BENGALI */ + { 268, 19, 17}, /* BENG */ + { 670, 19, 18}, /* GURMUKHI */ + { 671, 19, 18}, /* GURU */ + { 666, 19, 19}, /* GUJARATI */ + { 667, 19, 19}, /* GUJR */ + {1129, 19, 20}, /* ORIYA */ + {1132, 19, 20}, /* ORYA */ + {1378, 19, 21}, /* TAMIL */ + {1381, 19, 21}, /* TAML */ + {1393, 19, 22}, /* TELUGU */ + {1392, 19, 22}, /* TELU */ + { 801, 19, 23}, /* KANNADA */ + { 822, 19, 23}, /* KNDA */ + { 917, 19, 24}, /* MALAYALAM */ + {1009, 19, 24}, /* MLYM */ + {1287, 19, 25}, /* SINHALA */ + {1286, 19, 25}, /* SINH */ + {1401, 19, 26}, /* THAI */ + { 832, 19, 27}, /* LAO */ + { 833, 19, 27}, /* LAOO */ + {1403, 19, 28}, /* TIBETAN */ + {1404, 19, 28}, /* TIBT */ + {1029, 19, 29}, /* MYANMAR */ + {1036, 19, 29}, /* MYMR */ + { 635, 19, 30}, /* GEORGIAN */ + { 634, 19, 30}, /* GEOR */ + { 684, 19, 31}, /* HANGUL */ + { 683, 19, 31}, /* HANG */ + { 584, 19, 32}, /* ETHIOPIC */ + { 583, 19, 32}, /* ETHI */ + { 379, 19, 33}, /* CHEROKEE */ + { 378, 19, 33}, /* CHER */ + { 317, 19, 34}, /* CANADIANABORIGINAL */ + { 321, 19, 34}, /* CANS */ + {1105, 19, 35}, /* OGHAM */ + {1104, 19, 35}, /* OGAM */ + {1246, 19, 36}, /* RUNIC */ + {1247, 19, 36}, /* RUNR */ + {1364, 19, 37}, /* TAGALOG */ + {1398, 19, 37}, /* TGLG */ + { 698, 19, 38}, /* HANUNOO */ + { 695, 19, 38}, /* HANO */ + { 309, 19, 39}, /* BUHID */ + { 308, 19, 39}, /* BUHD */ + {1366, 19, 40}, /* TAGBANWA */ + {1365, 19, 40}, /* TAGB */ + { 814, 19, 41}, /* KHMER */ + { 816, 19, 41}, /* KHMR */ + {1019, 19, 42}, /* MONGOLIAN */ + {1018, 19, 42}, /* MONG */ + { 873, 19, 43}, /* LIMBU */ + { 872, 19, 43}, /* LIMB */ + {1369, 19, 44}, /* TAILE */ + {1376, 19, 44}, /* TALE */ + {1056, 19, 45}, /* NEWTAILUE */ + {1377, 19, 45}, /* TALU */ + { 307, 19, 46}, /* BUGINESE */ + { 306, 19, 46}, /* BUGI */ + {1370, 19, 47}, /* TAITHAM */ + { 831, 19, 47}, /* LANA */ + { 252, 19, 48}, /* BALINESE */ + { 251, 19, 48}, /* BALI */ + {1320, 19, 49}, /* SUNDANESE */ + {1319, 19, 49}, /* SUND */ + { 260, 19, 50}, /* BATAK */ + { 261, 19, 50}, /* BATK */ + { 867, 19, 51}, /* LEPCHA */ + { 866, 19, 51}, /* LEPC */ + {1109, 19, 52}, /* OLCHIKI */ + {1110, 19, 52}, /* OLCK */ + { 300, 19, 53}, /* BRAILLE */ + { 299, 19, 53}, /* BRAI */ + { 642, 19, 54}, /* GLAGOLITIC */ + { 641, 19, 54}, /* GLAG */ + {1405, 19, 55}, /* TIFINAGH */ + {1397, 19, 55}, /* TFNG */ + { 682, 19, 56}, /* HAN */ + { 691, 19, 56}, /* HANI */ + { 714, 19, 57}, /* HIRAGANA */ + { 713, 19, 57}, /* HIRA */ + { 804, 19, 58}, /* KATAKANA */ + { 790, 19, 58}, /* KANA */ + {1505, 19, 59}, /* YI */ + {1506, 19, 59}, /* YIII */ + { 884, 19, 60}, /* LISU */ + {1447, 19, 61}, /* VAI */ + {1448, 19, 61}, /* VAII */ + { 254, 19, 62}, /* BAMUM */ + { 253, 19, 62}, /* BAMU */ + {1351, 19, 63}, /* SYLOTINAGRI */ + {1350, 19, 63}, /* SYLO */ + {1178, 19, 64}, /* PHAGSPA */ + {1177, 19, 64}, /* PHAG */ + {1257, 19, 65}, /* SAURASHTRA */ + {1256, 19, 65}, /* SAUR */ + { 809, 19, 66}, /* KAYAHLI */ + { 789, 19, 66}, /* KALI */ + {1228, 19, 67}, /* REJANG */ + {1238, 19, 67}, /* RJNG */ + { 774, 19, 68}, /* JAVANESE */ + { 773, 19, 68}, /* JAVA */ + { 372, 19, 69}, /* CHAM */ + {1371, 19, 70}, /* TAIVIET */ + {1388, 19, 70}, /* TAVT */ + { 982, 19, 71}, /* MEETEIMAYEK */ + {1024, 19, 71}, /* MTEI */ + { 877, 19, 72}, /* LINEARB */ + { 875, 19, 72}, /* LINB */ + { 906, 19, 73}, /* LYCIAN */ + { 905, 19, 73}, /* LYCI */ + { 324, 19, 74}, /* CARIAN */ + { 323, 19, 74}, /* CARI */ + {1112, 19, 75}, /* OLDITALIC */ + { 769, 19, 75}, /* ITAL */ + { 650, 19, 76}, /* GOTHIC */ + { 649, 19, 76}, /* GOTH */ + {1114, 19, 77}, /* OLDPERMIC */ + {1175, 19, 77}, /* PERM */ + {1434, 19, 78}, /* UGARITIC */ + {1433, 19, 78}, /* UGAR */ + {1115, 19, 79}, /* OLDPERSIAN */ + {1495, 19, 79}, /* XPEO */ + { 511, 19, 80}, /* DESERET */ + { 537, 19, 80}, /* DSRT */ + {1276, 19, 81}, /* SHAVIAN */ + {1277, 19, 81}, /* SHAW */ + {1136, 19, 82}, /* OSMANYA */ + {1135, 19, 82}, /* OSMA */ + {1133, 19, 83}, /* OSAGE */ + {1134, 19, 83}, /* OSGE */ + { 557, 19, 84}, /* ELBASAN */ + { 556, 19, 84}, /* ELBA */ + { 329, 19, 85}, /* CAUCASIANALBANIAN */ + { 178, 19, 85}, /* AGHB */ + {1466, 19, 86}, /* VITHKUQI */ + {1465, 19, 86}, /* VITH */ + {1410, 19, 87}, /* TODHRI */ + {1411, 19, 87}, /* TODR */ + { 876, 19, 88}, /* LINEARA */ + { 874, 19, 88}, /* LINA */ + { 481, 19, 89}, /* CYPRIOT */ + { 468, 19, 89}, /* CPRT */ + { 743, 19, 90}, /* IMPERIALARAMAIC */ + { 228, 19, 90}, /* ARMI */ + {1161, 19, 91}, /* PALMYRENE */ + {1160, 19, 91}, /* PALM */ + {1040, 19, 92}, /* NABATAEAN */ + {1050, 19, 92}, /* NBAT */ + { 700, 19, 93}, /* HATRAN */ + { 699, 19, 93}, /* HATR */ + {1184, 19, 94}, /* PHOENICIAN */ + {1183, 19, 94}, /* PHNX */ + { 908, 19, 95}, /* LYDIAN */ + { 907, 19, 95}, /* LYDI */ + { 990, 19, 96}, /* MEROITICHIEROGLYPHS */ + { 988, 19, 96}, /* MERO */ + { 989, 19, 97}, /* MEROITICCURSIVE */ + { 987, 19, 97}, /* MERC */ + { 812, 19, 98}, /* KHAROSHTHI */ + { 811, 19, 98}, /* KHAR */ + {1117, 19, 99}, /* OLDSOUTHARABIAN */ + {1255, 19, 99}, /* SARB */ + {1113, 19, 100}, /* OLDNORTHARABIAN */ + {1047, 19, 100}, /* NARB */ + { 933, 19, 101}, /* MANICHAEAN */ + { 932, 19, 101}, /* MANI */ + { 246, 19, 102}, /* AVESTAN */ + { 247, 19, 102}, /* AVST */ + { 759, 19, 103}, /* INSCRIPTIONALPARTHIAN */ + {1208, 19, 103}, /* PRTI */ + { 758, 19, 104}, /* INSCRIPTIONALPAHLAVI */ + {1181, 19, 104}, /* PHLI */ + {1210, 19, 105}, /* PSALTERPAHLAVI */ + {1182, 19, 105}, /* PHLP */ + {1118, 19, 106}, /* OLDTURKIC */ + {1130, 19, 106}, /* ORKH */ + {1111, 19, 107}, /* OLDHUNGARIAN */ + { 722, 19, 107}, /* HUNG */ + { 692, 19, 108}, /* HANIFIROHINGYA */ + {1242, 19, 108}, /* ROHG */ + { 624, 19, 109}, /* GARAY */ + { 623, 19, 109}, /* GARA */ + {1504, 19, 110}, /* YEZIDI */ + {1503, 19, 110}, /* YEZI */ + {1116, 19, 111}, /* OLDSOGDIAN */ + {1301, 19, 111}, /* SOGO */ + {1300, 19, 112}, /* SOGDIAN */ + {1299, 19, 112}, /* SOGD */ + {1119, 19, 113}, /* OLDUYGHUR */ + {1152, 19, 113}, /* OUGR */ + { 383, 19, 114}, /* CHORASMIAN */ + { 384, 19, 114}, /* CHRS */ + { 559, 19, 115}, /* ELYMAIC */ + { 558, 19, 115}, /* ELYM */ + { 297, 19, 116}, /* BRAHMI */ + { 296, 19, 116}, /* BRAH */ + { 787, 19, 117}, /* KAITHI */ + { 825, 19, 117}, /* KTHI */ + {1303, 19, 118}, /* SORASOMPENG */ + {1302, 19, 118}, /* SORA */ + { 371, 19, 119}, /* CHAKMA */ + { 315, 19, 119}, /* CAKM */ + { 911, 19, 120}, /* MAHAJANI */ + { 912, 19, 120}, /* MAHJ */ + {1275, 19, 121}, /* SHARADA */ + {1280, 19, 121}, /* SHRD */ + { 818, 19, 122}, /* KHOJKI */ + { 817, 19, 122}, /* KHOJ */ + {1026, 19, 123}, /* MULTANI */ + {1025, 19, 123}, /* MULT */ + { 819, 19, 124}, /* KHUDAWADI */ + {1284, 19, 124}, /* SIND */ + { 652, 19, 125}, /* GRANTHA */ + { 651, 19, 125}, /* GRAN */ + {1427, 19, 126}, /* TULUTIGALARI */ + {1428, 19, 126}, /* TUTG */ + {1054, 19, 127}, /* NEWA */ + {1407, 19, 128}, /* TIRHUTA */ + {1406, 19, 128}, /* TIRH */ + {1282, 19, 129}, /* SIDDHAM */ + {1281, 19, 129}, /* SIDD */ + {1011, 19, 130}, /* MODI */ + {1375, 19, 131}, /* TAKRI */ + {1374, 19, 131}, /* TAKR */ + { 180, 19, 132}, /* AHOM */ + { 530, 19, 133}, /* DOGRA */ + { 529, 19, 133}, /* DOGR */ + {1477, 19, 134}, /* WARANGCITI */ + {1476, 19, 134}, /* WARA */ + { 528, 19, 135}, /* DIVESAKURU */ + { 525, 19, 135}, /* DIAK */ + {1045, 19, 136}, /* NANDINAGARI */ + {1044, 19, 136}, /* NAND */ + {1516, 19, 137}, /* ZANABAZARSQUARE */ + {1517, 19, 137}, /* ZANB */ + {1305, 19, 138}, /* SOYOMBO */ + {1304, 19, 138}, /* SOYO */ + {1168, 19, 139}, /* PAUCINHAU */ + {1167, 19, 139}, /* PAUC */ + {1324, 19, 140}, /* SUNUWAR */ + {1323, 19, 140}, /* SUNU */ + { 271, 19, 141}, /* BHAIKSUKI */ + { 272, 19, 141}, /* BHKS */ + { 962, 19, 142}, /* MARCHEN */ + { 961, 19, 142}, /* MARC */ + { 964, 19, 143}, /* MASARAMGONDI */ + { 648, 19, 143}, /* GONM */ + { 669, 19, 144}, /* GUNJALAGONDI */ + { 647, 19, 144}, /* GONG */ + { 916, 19, 145}, /* MAKASAR */ + { 915, 19, 145}, /* MAKA */ + { 808, 19, 146}, /* KAWI */ + { 471, 19, 147}, /* CUNEIFORM */ + {1496, 19, 147}, /* XSUX */ + { 483, 19, 148}, /* CYPROMINOAN */ + { 467, 19, 148}, /* CPMN */ + { 553, 19, 149}, /* EGYPTIANHIEROGLYPHS */ + { 551, 19, 149}, /* EGYP */ + { 201, 19, 150}, /* ANATOLIANHIEROGLYPHS */ + { 716, 19, 150}, /* HLUW */ + { 672, 19, 151}, /* GURUNGKHEMA */ + { 668, 19, 151}, /* GUKH */ + {1022, 19, 152}, /* MRO */ + {1023, 19, 152}, /* MROO */ + {1383, 19, 153}, /* TANGSA */ + {1409, 19, 153}, /* TNSA */ + { 259, 19, 154}, /* BASSAVAH */ + { 258, 19, 154}, /* BASS */ + {1159, 19, 155}, /* PAHAWHHMONG */ + { 717, 19, 155}, /* HMNG */ + { 820, 19, 156}, /* KIRATRAI */ + { 824, 19, 156}, /* KRAI */ + { 978, 19, 157}, /* MEDEFAIDRIN */ + { 979, 19, 157}, /* MEDF */ + { 991, 19, 158}, /* MIAO */ + {1191, 19, 158}, /* PLRD */ + {1384, 19, 159}, /* TANGUT */ + {1382, 19, 159}, /* TANG */ + {1097, 19, 160}, /* NUSHU */ + {1085, 19, 160}, /* NSHU */ + { 813, 19, 161}, /* KHITANSMALLSCRIPT */ + { 821, 19, 161}, /* KITS */ + { 541, 19, 162}, /* DUPLOYAN */ + { 540, 19, 162}, /* DUPL */ + {1283, 19, 163}, /* SIGNWRITING */ + {1274, 19, 163}, /* SGNW */ + {1100, 19, 164}, /* NYIAKENGPUACHUEHMONG */ + { 718, 19, 164}, /* HMNP */ + {1421, 19, 165}, /* TOTO */ + {1475, 19, 166}, /* WANCHO */ + {1480, 19, 166}, /* WCHO */ + {1042, 19, 167}, /* NAGMUNDARI */ + {1041, 19, 167}, /* NAGM */ + {1121, 19, 168}, /* OLONAL */ + {1125, 19, 168}, /* ONAO */ + { 986, 19, 169}, /* MENDEKIKAKUI */ + { 985, 19, 169}, /* MEND */ + { 172, 19, 170}, /* ADLAM */ + { 173, 19, 170}, /* ADLM */ + { 806, 19, 171}, /* KATAKANAORHIRAGANA */ + { 720, 19, 171}, /* HRKT */ + {1137, 20, 0}, /* OTHER */ + {1497, 20, 0}, /* XX */ + {1306, 20, 1}, /* SP */ + { 871, 20, 2}, /* LF */ + { 469, 20, 3}, /* CR */ + {1316, 20, 4}, /* STERM */ + {1315, 20, 4}, /* ST */ + { 422, 20, 5}, /* CLOSE */ + { 421, 20, 5}, /* CL */ + {1260, 20, 6}, /* SCONTINUE */ + {1259, 20, 6}, /* SC */ + { 240, 20, 7}, /* ATERM */ + { 235, 20, 7}, /* AT */ + {1093, 20, 8}, /* NUMERIC */ + {1088, 20, 8}, /* NU */ + {1443, 20, 9}, /* UPPER */ + {1442, 20, 9}, /* UP */ + { 892, 20, 10}, /* LOWER */ + { 889, 20, 10}, /* LO */ + {1271, 20, 11}, /* SEP */ + {1265, 20, 11}, /* SE */ + { 616, 20, 12}, /* FORMAT */ + { 614, 20, 12}, /* FO */ + {1120, 20, 13}, /* OLETTER */ + { 857, 20, 13}, /* LE */ + { 599, 20, 14}, /* EXTEND */ + { 596, 20, 14}, /* EX */ + {1137, 21, 0}, /* OTHER */ + {1497, 21, 0}, /* XX */ + { 871, 21, 1}, /* LF */ + {1055, 21, 2}, /* NEWLINE */ + {1069, 21, 2}, /* NL */ + { 469, 21, 3}, /* CR */ + {1488, 21, 4}, /* WSEGSPACE */ + { 535, 21, 5}, /* DOUBLEQUOTE */ + { 536, 21, 5}, /* DQ */ + {1285, 21, 6}, /* SINGLEQUOTE */ + {1312, 21, 6}, /* SQ */ + { 993, 21, 7}, /* MIDNUM */ + {1010, 21, 7}, /* MN */ + { 994, 21, 8}, /* MIDNUMLET */ + { 973, 21, 8}, /* MB */ + {1093, 21, 9}, /* NUMERIC */ + {1088, 21, 9}, /* NU */ + { 992, 21, 10}, /* MIDLETTER */ + {1008, 21, 10}, /* ML */ + { 192, 21, 11}, /* ALETTER */ + { 857, 21, 11}, /* LE */ + { 602, 21, 12}, /* EXTENDNUMLET */ + { 596, 21, 12}, /* EX */ + { 616, 21, 13}, /* FORMAT */ + { 614, 21, 13}, /* FO */ + { 599, 21, 14}, /* EXTEND */ + { 704, 21, 15}, /* HEBREWLETTER */ + { 715, 21, 15}, /* HL */ + {1526, 21, 16}, /* ZWJ */ + { 804, 21, 17}, /* KATAKANA */ + { 785, 21, 17}, /* KA */ + {1225, 21, 18}, /* REGIONALINDICATOR */ + {1231, 21, 18}, /* RI */ + { 547, 21, 19}, /* EBASE */ + { 546, 21, 19}, /* EB */ + { 548, 21, 20}, /* EBASEGAZ */ + { 549, 21, 20}, /* EBG */ + { 562, 21, 21}, /* EMODIFIER */ + { 560, 21, 21}, /* EM */ + { 646, 21, 22}, /* GLUEAFTERZWJ */ + { 625, 21, 22}, /* GAZ */ +}; + +/* Codepoints which expand on full case-folding. */ +RE_UINT16 re_expand_on_folding[] = { + 223, 304, 329, 496, 912, 944, 1415, 7830, + 7831, 7832, 7833, 7834, 7838, 8016, 8018, 8020, + 8022, 8064, 8065, 8066, 8067, 8068, 8069, 8070, + 8071, 8072, 8073, 8074, 8075, 8076, 8077, 8078, + 8079, 8080, 8081, 8082, 8083, 8084, 8085, 8086, + 8087, 8088, 8089, 8090, 8091, 8092, 8093, 8094, + 8095, 8096, 8097, 8098, 8099, 8100, 8101, 8102, + 8103, 8104, 8105, 8106, 8107, 8108, 8109, 8110, + 8111, 8114, 8115, 8116, 8118, 8119, 8124, 8130, + 8131, 8132, 8134, 8135, 8140, 8146, 8147, 8150, + 8151, 8162, 8163, 8164, 8166, 8167, 8178, 8179, + 8180, 8182, 8183, 8188, 64256, 64257, 64258, 64259, + 64260, 64261, 64262, 64275, 64276, 64277, 64278, 64279 +}; + +/* Alphabetic. */ +static RE_UINT8 re_alphabetic_table_1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 13, + 13, 13, 13, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 15, 16, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 17, 10, 10, 10, 10, 10, 10, 10, 10, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 10, 30, 13, 31, 13, 13, + 32, 33, 10, 10, 10, 10, 10, 10, 34, 10, 35, 36, 13, 13, 13, 13, + 13, 37, 13, 38, 10, 10, 10, 10, 10, 10, 10, 39, 40, 10, 10, 41, + 10, 10, 10, 10, 10, 42, 10, 43, 44, 45, 46, 47, 48, 10, 10, 10, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 49, 13, 13, 13, 50, 51, 13, + 13, 13, 13, 52, 13, 13, 13, 13, 13, 13, 53, 54, 10, 10, 55, 10, + 13, 13, 13, 13, 56, 13, 13, 13, 57, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 +}; + +static RE_UINT16 re_alphabetic_table_2[] = { + 0, 0, 1, 1, 0, 2, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 5, 6, 0, 0, 7, 8, 9, 10, 4, 11, + 4, 4, 4, 4, 12, 4, 4, 4, 4, 13, 14, 4, 15, 16, 17, 18, + 19, 4, 20, 21, 4, 4, 22, 23, 24, 4, 25, 4, 4, 26, 27, 28, + 29, 30, 31, 32, 33, 4, 34, 35, 4, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 47, 48, 49, 50, 51, 48, 52, 53, 54, 55, 56, 0, + 57, 58, 59, 60, 61, 62, 63, 64, 57, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 74, 0, 75, 76, 77, 0, 78, 0, 79, 80, 81, 82, 0, 0, + 4, 83, 24, 4, 84, 4, 85, 86, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 87, 4, 88, 89, 90, 4, 91, 4, 73, 0, 92, 4, 4, 93, + 72, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 94, 1, 4, 4, 95, 96, 97, 97, 98, 4, 99, 100, 0, + 0, 4, 4, 31, 4, 32, 4, 101, 102, 103, 24, 104, 4, 105, 106, 0, + 107, 4, 102, 108, 0, 109, 110, 0, 4, 111, 112, 0, 4, 113, 4, 114, + 4, 115, 116, 117, 32, 65, 0, 118, 4, 4, 4, 4, 4, 4, 119, 120, + 4, 4, 4, 4, 4, 4, 4, 4, 93, 4, 121, 117, 4, 122, 123, 124, + 0, 0, 0, 125, 126, 0, 0, 0, 127, 128, 129, 4, 15, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 130, 4, 106, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 131, 4, 85, 4, 132, 115, 133, 133, 4, + 0, 134, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 135, 136, 72, 4, 137, 72, 4, 86, 138, 13, 4, 4, 139, 4, 0, 24, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 30, 0, 24, 117, 4, 4, 4, 4, 4, 4, 4, 4, + 140, 141, 4, 142, 4, 4, 4, 92, 143, 144, 4, 4, 145, 4, 146, 147, + 148, 149, 4, 97, 4, 4, 150, 151, 27, 32, 152, 82, 4, 153, 134, 154, + 4, 115, 155, 156, 4, 102, 157, 158, 159, 160, 86, 161, 4, 4, 4, 162, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 163, 164, 107, + 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 165, 4, 4, 166, 0, 167, 168, 169, 4, 4, 26, 119, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 117, 24, 4, 170, 4, 149, 171, + 0, 0, 0, 172, 4, 4, 4, 82, 0, 1, 1, 173, 4, 102, 174, 0, + 175, 176, 177, 0, 4, 4, 4, 73, 0, 0, 4, 120, 0, 0, 0, 0, + 0, 0, 0, 0, 82, 4, 178, 0, 4, 25, 32, 73, 117, 4, 179, 0, + 4, 4, 4, 4, 117, 24, 180, 107, 4, 181, 4, 182, 183, 184, 4, 97, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 115, 101, 149, 148, 185, 0, 0, + 186, 187, 101, 115, 102, 0, 0, 188, 101, 166, 0, 0, 4, 189, 0, 0, + 190, 101, 0, 82, 82, 0, 79, 191, 4, 101, 101, 152, 26, 0, 0, 0, + 4, 4, 15, 0, 4, 152, 4, 152, 4, 149, 27, 192, 193, 0, 0, 0, + 0, 0, 0, 0, 4, 194, 195, 196, 82, 197, 193, 24, 198, 24, 191, 115, + 4, 4, 193, 199, 4, 31, 200, 15, 4, 152, 201, 202, 4, 4, 203, 0, + 204, 205, 198, 0, 206, 207, 4, 15, 39, 48, 208, 60, 209, 11, 210, 0, + 4, 4, 211, 198, 4, 4, 212, 0, 0, 0, 0, 0, 4, 213, 214, 0, + 4, 102, 215, 0, 4, 216, 0, 0, 65, 162, 217, 0, 0, 0, 0, 0, + 4, 31, 0, 0, 0, 4, 4, 218, 219, 220, 221, 0, 0, 222, 29, 223, + 4, 224, 24, 4, 225, 24, 4, 31, 0, 0, 0, 0, 0, 0, 4, 78, + 226, 227, 78, 147, 170, 228, 0, 0, 229, 230, 231, 232, 233, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 115, 234, 235, 78, 0, 0, 236, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 166, 0, 0, 0, + 4, 4, 4, 139, 4, 4, 4, 4, 4, 4, 60, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 4, 4, 178, + 4, 92, 237, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 73, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 217, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 4, 139, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 31, 102, 24, 4, 102, 24, 155, 4, 92, 60, 238, 92, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 30, 0, 0, 0, 0, + 0, 0, 4, 4, 0, 0, 0, 0, 4, 4, 239, 4, 240, 0, 0, 241, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 242, + 4, 4, 4, 4, 4, 4, 101, 218, 15, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 244, 245, 201, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 107, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 246, 247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 248, 4, 249, 250, 251, 4, 252, 253, 254, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 255, 256, 86, 248, 248, 257, 257, 226, 226, 258, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 102, 259, 0, 0, 0, 0, 0, 0, + 260, 261, 4, 155, 134, 0, 0, 0, 4, 262, 263, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 24, 155, 4, 264, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 24, 264, 0, 0, 0, 0, 0, 0, 24, 265, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 266, + 4, 4, 4, 4, 4, 4, 191, 0, 4, 4, 267, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 251, 268, 269, 270, 271, 272, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 161, 161, 106, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 166, 4, 4, 4, 4, 4, 4, + 117, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 273, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 274, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 32, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 92, 0, 0 +}; + +static RE_UINT8 re_alphabetic_table_3[] = { + 0, 0, 0, 0, 254, 255, 255, 7, 0, 4, 32, 4, 255, 255, 127, 255, + 255, 255, 255, 255, 195, 255, 3, 0, 31, 80, 0, 0, 32, 0, 0, 0, + 248, 255, 223, 188, 64, 215, 255, 255, 251, 255, 255, 255, 255, 255, 191, 255, + 3, 252, 255, 255, 255, 255, 254, 255, 255, 255, 127, 2, 255, 1, 0, 0, + 0, 0, 255, 191, 182, 0, 255, 255, 255, 135, 7, 0, 0, 0, 255, 7, + 255, 255, 255, 254, 0, 192, 255, 255, 255, 255, 239, 31, 254, 225, 0, 156, + 0, 0, 255, 255, 0, 224, 255, 255, 255, 255, 3, 0, 0, 252, 255, 255, + 255, 7, 48, 4, 255, 255, 255, 252, 255, 31, 0, 0, 255, 255, 255, 1, + 255, 7, 255, 255, 255, 126, 128, 0, 255, 3, 240, 255, 248, 3, 255, 255, + 255, 255, 255, 239, 255, 223, 225, 255, 15, 0, 254, 255, 239, 159, 249, 255, + 255, 253, 197, 227, 159, 89, 128, 176, 15, 0, 3, 16, 238, 135, 249, 255, + 255, 253, 109, 195, 135, 25, 2, 94, 0, 0, 63, 0, 238, 191, 251, 255, + 255, 253, 237, 227, 191, 27, 1, 0, 15, 0, 0, 30, 238, 159, 249, 255, + 159, 25, 192, 176, 15, 0, 2, 0, 236, 199, 61, 214, 24, 199, 255, 195, + 199, 29, 129, 0, 255, 223, 253, 255, 255, 253, 255, 227, 223, 29, 96, 39, + 15, 0, 0, 0, 239, 223, 253, 255, 255, 253, 239, 227, 223, 29, 96, 96, + 15, 0, 14, 0, 255, 255, 255, 231, 223, 93, 240, 128, 15, 0, 0, 252, + 238, 255, 127, 252, 255, 255, 251, 47, 127, 128, 95, 255, 0, 0, 12, 0, + 254, 255, 255, 255, 255, 255, 255, 7, 127, 32, 0, 0, 214, 247, 255, 255, + 175, 255, 255, 59, 95, 32, 0, 240, 1, 0, 0, 0, 255, 254, 255, 255, + 255, 31, 254, 255, 15, 255, 255, 254, 255, 255, 255, 31, 255, 255, 127, 249, + 255, 255, 0, 60, 191, 32, 255, 255, 255, 255, 255, 247, 255, 61, 127, 61, + 255, 61, 255, 255, 255, 255, 61, 127, 61, 255, 127, 255, 255, 255, 61, 255, + 255, 255, 0, 0, 255, 255, 63, 63, 255, 159, 255, 255, 255, 199, 255, 1, + 255, 255, 15, 128, 255, 255, 15, 0, 255, 223, 13, 0, 255, 255, 207, 255, + 255, 1, 128, 16, 255, 255, 63, 0, 255, 255, 255, 127, 255, 15, 255, 1, + 255, 63, 31, 0, 255, 15, 255, 255, 255, 3, 0, 0, 255, 255, 255, 15, + 254, 255, 31, 0, 128, 0, 0, 128, 1, 112, 0, 0, 255, 255, 239, 255, + 239, 31, 0, 0, 255, 243, 0, 252, 191, 255, 3, 0, 255, 255, 127, 0, + 0, 224, 0, 252, 255, 255, 255, 63, 0, 222, 111, 4, 0, 0, 248, 255, + 255, 255, 31, 0, 63, 63, 255, 170, 255, 255, 223, 95, 220, 31, 207, 15, + 255, 31, 220, 31, 0, 0, 2, 128, 0, 0, 255, 31, 132, 252, 47, 62, + 80, 189, 255, 243, 224, 67, 0, 0, 0, 0, 192, 255, 31, 120, 12, 0, + 255, 128, 0, 0, 127, 127, 127, 127, 0, 128, 0, 0, 224, 0, 0, 0, + 254, 3, 62, 31, 255, 255, 127, 224, 224, 255, 255, 255, 255, 127, 0, 0, + 255, 31, 255, 255, 0, 12, 0, 0, 255, 127, 240, 143, 0, 0, 128, 255, + 252, 255, 255, 255, 255, 249, 255, 255, 255, 63, 235, 31, 0, 0, 252, 255, + 191, 255, 255, 255, 255, 0, 0, 0, 47, 0, 0, 0, 0, 0, 252, 232, + 255, 255, 7, 0, 255, 255, 247, 255, 255, 255, 0, 124, 255, 63, 0, 0, + 255, 255, 127, 252, 5, 0, 0, 56, 255, 255, 60, 0, 126, 126, 126, 0, + 127, 127, 255, 255, 255, 3, 255, 255, 255, 7, 0, 0, 15, 0, 255, 255, + 127, 248, 255, 255, 255, 63, 255, 255, 255, 255, 255, 3, 127, 0, 248, 224, + 255, 253, 127, 95, 219, 255, 255, 255, 255, 255, 252, 255, 0, 0, 255, 15, + 0, 0, 223, 255, 192, 255, 255, 255, 252, 252, 252, 28, 255, 239, 255, 255, + 127, 255, 255, 183, 255, 63, 255, 63, 255, 255, 1, 0, 15, 255, 62, 0, + 255, 255, 15, 255, 255, 0, 255, 255, 15, 0, 255, 247, 255, 247, 183, 255, + 251, 255, 251, 27, 255, 255, 253, 7, 63, 253, 255, 255, 255, 255, 191, 145, + 255, 255, 55, 0, 255, 255, 255, 192, 111, 240, 239, 254, 31, 0, 0, 0, + 63, 130, 255, 255, 63, 0, 0, 0, 255, 27, 3, 0, 28, 0, 0, 0, + 0, 0, 0, 16, 128, 0, 255, 255, 3, 0, 0, 0, 0, 0, 62, 0, + 4, 0, 255, 255, 240, 0, 255, 255, 255, 255, 71, 0, 30, 192, 0, 20, + 255, 255, 251, 255, 255, 255, 159, 192, 127, 189, 255, 191, 255, 1, 255, 255, + 159, 25, 129, 224, 255, 75, 255, 255, 165, 55, 10, 0, 187, 7, 0, 128, + 179, 0, 0, 0, 255, 255, 63, 127, 0, 0, 0, 63, 17, 0, 0, 0, + 255, 255, 63, 1, 127, 0, 0, 0, 0, 0, 0, 128, 127, 242, 111, 255, + 255, 255, 191, 153, 7, 0, 0, 0, 255, 252, 255, 255, 26, 0, 0, 0, + 255, 255, 231, 127, 255, 255, 255, 32, 255, 253, 255, 255, 255, 255, 127, 127, + 255, 254, 127, 0, 127, 251, 255, 255, 255, 255, 127, 180, 203, 0, 0, 0, + 191, 253, 255, 255, 255, 127, 123, 1, 255, 255, 253, 255, 255, 255, 255, 199, + 0, 0, 1, 0, 126, 0, 0, 0, 248, 255, 255, 224, 255, 135, 255, 255, + 255, 128, 255, 255, 11, 0, 3, 0, 255, 255, 255, 0, 0, 0, 239, 111, + 7, 0, 4, 0, 0, 0, 39, 0, 255, 7, 255, 31, 255, 1, 255, 67, + 255, 255, 223, 255, 255, 255, 255, 223, 100, 222, 255, 235, 239, 255, 255, 255, + 191, 231, 223, 223, 255, 255, 255, 123, 95, 252, 253, 255, 63, 255, 255, 255, + 253, 255, 255, 247, 255, 127, 255, 255, 247, 15, 0, 0, 224, 7, 0, 0, + 127, 255, 255, 249, 219, 7, 255, 255, 255, 31, 128, 63, 0, 64, 0, 0, + 255, 15, 0, 0, 255, 63, 1, 0, 127, 111, 255, 127, 143, 8, 0, 0, + 150, 254, 247, 10, 132, 234, 150, 170, 150, 247, 247, 94, 255, 251, 255, 15, + 238, 251, 255, 15, 3, 0, 255, 255, 1, 0, 255, 255 +}; + +RE_UINT32 re_get_alphabetic(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_alphabetic_table_1[field_2]; + v = re_alphabetic_table_2[(v << 5) | field_1]; + v = re_alphabetic_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Alphanumeric. */ +static RE_UINT8 re_alphanumeric_table_1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 13, + 13, 13, 13, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 15, 16, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 17, 10, 10, 10, 10, 10, 10, 10, 10, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 10, 30, 13, 31, 13, 13, + 32, 33, 10, 10, 10, 10, 10, 10, 34, 10, 35, 36, 13, 13, 13, 13, + 13, 37, 13, 38, 10, 10, 10, 10, 10, 10, 10, 39, 40, 10, 10, 41, + 10, 10, 10, 42, 10, 43, 10, 44, 45, 46, 47, 48, 49, 10, 50, 10, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 51, 13, 13, 13, 52, 53, 13, + 13, 13, 13, 54, 13, 13, 13, 13, 13, 13, 55, 56, 10, 10, 57, 10, + 13, 13, 13, 13, 58, 13, 13, 13, 59, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 +}; + +static RE_UINT16 re_alphanumeric_table_2[] = { + 0, 1, 2, 2, 0, 3, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 6, 7, 0, 0, 8, 9, 10, 11, 5, 12, + 5, 5, 5, 5, 13, 5, 5, 5, 5, 14, 15, 5, 16, 17, 18, 19, + 20, 5, 21, 22, 5, 5, 23, 24, 25, 5, 26, 5, 5, 27, 5, 28, + 29, 30, 31, 32, 33, 5, 34, 35, 5, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 47, 48, 49, 50, 51, 48, 52, 53, 54, 55, 56, 57, + 58, 59, 60, 61, 62, 63, 64, 65, 58, 66, 67, 68, 69, 70, 71, 72, + 73, 74, 75, 0, 76, 77, 78, 0, 79, 80, 81, 82, 83, 84, 0, 0, + 5, 85, 86, 5, 87, 5, 88, 89, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 90, 5, 91, 92, 93, 5, 94, 5, 74, 0, 95, 5, 5, 96, + 73, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 97, 2, 5, 5, 98, 99, 100, 100, 101, 5, 102, 103, 80, + 1, 5, 5, 31, 5, 32, 5, 104, 105, 106, 107, 108, 5, 109, 110, 0, + 111, 5, 105, 112, 110, 113, 114, 0, 5, 115, 116, 0, 5, 117, 5, 118, + 5, 119, 120, 87, 32, 66, 0, 121, 5, 5, 5, 5, 5, 5, 122, 123, + 5, 5, 5, 5, 5, 5, 5, 5, 96, 5, 124, 87, 5, 125, 126, 127, + 0, 0, 0, 128, 129, 0, 0, 0, 130, 131, 132, 5, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 133, 5, 80, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 134, 5, 88, 5, 135, 119, 136, 136, 5, + 0, 137, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 138, 139, 73, 5, 140, 73, 5, 89, 141, 14, 5, 5, 142, 5, 0, 25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 30, 0, 25, 87, 5, 5, 5, 5, 5, 5, 5, 5, + 143, 144, 5, 145, 5, 5, 5, 95, 146, 147, 5, 5, 148, 5, 149, 150, + 151, 152, 5, 100, 5, 5, 153, 154, 5, 32, 155, 84, 5, 156, 157, 105, + 5, 119, 158, 159, 5, 105, 160, 161, 162, 163, 89, 86, 5, 5, 5, 164, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 165, 166, 111, + 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 167, 5, 5, 168, 0, 169, 170, 171, 5, 5, 27, 122, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 87, 25, 5, 172, 5, 152, 173, + 0, 0, 0, 174, 5, 5, 5, 84, 1, 2, 2, 107, 5, 105, 175, 0, + 176, 177, 178, 0, 5, 5, 5, 74, 0, 0, 5, 123, 0, 0, 0, 0, + 0, 0, 0, 0, 84, 5, 179, 0, 5, 26, 32, 74, 87, 5, 180, 0, + 5, 5, 5, 5, 87, 86, 181, 111, 5, 182, 5, 183, 184, 185, 5, 100, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 119, 104, 152, 151, 186, 0, 0, + 187, 188, 104, 119, 105, 0, 0, 189, 104, 168, 0, 0, 5, 190, 0, 0, + 191, 104, 0, 84, 84, 0, 81, 192, 5, 104, 104, 155, 27, 0, 0, 0, + 5, 5, 16, 0, 5, 155, 5, 155, 5, 193, 5, 194, 195, 0, 0, 0, + 0, 0, 0, 0, 5, 196, 197, 198, 84, 199, 195, 25, 200, 25, 192, 119, + 5, 5, 195, 201, 5, 31, 202, 203, 5, 204, 205, 206, 5, 5, 207, 0, + 208, 209, 200, 0, 210, 211, 5, 203, 39, 48, 212, 213, 214, 12, 215, 0, + 5, 5, 216, 200, 5, 5, 217, 0, 0, 0, 0, 0, 5, 218, 219, 0, + 5, 105, 220, 0, 5, 221, 86, 213, 66, 164, 222, 0, 0, 0, 0, 0, + 5, 31, 0, 0, 0, 5, 5, 223, 224, 225, 226, 0, 0, 227, 29, 228, + 5, 229, 25, 5, 230, 25, 5, 31, 0, 0, 0, 0, 0, 0, 5, 231, + 232, 233, 231, 150, 172, 234, 0, 0, 235, 236, 237, 238, 239, 80, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 119, 240, 241, 231, 0, 0, 242, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 168, 0, 0, 0, + 5, 5, 5, 142, 5, 5, 5, 5, 5, 5, 213, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 5, 5, 179, + 5, 95, 243, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 74, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 222, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 5, 244, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 31, 105, 86, 5, 105, 86, 245, 5, 95, 246, 247, 95, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 248, 0, 0, 0, 0, + 0, 0, 5, 5, 0, 0, 0, 0, 5, 5, 249, 5, 250, 0, 0, 251, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 252, + 5, 5, 5, 5, 5, 5, 104, 253, 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 255, 256, 205, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 111, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 257, 258, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 259, 5, 260, 261, 262, 5, 263, 264, 265, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 266, 267, 89, 259, 259, 268, 268, 232, 232, 269, 5, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 105, 270, 0, 0, 0, 0, 0, 0, + 271, 272, 5, 245, 137, 0, 0, 0, 5, 273, 274, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 25, 245, 5, 275, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 25, 275, 0, 0, 0, 0, 0, 0, 25, 276, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 277, + 5, 5, 5, 5, 5, 5, 192, 0, 5, 5, 278, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 262, 279, 280, 281, 282, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 86, 86, 80, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 168, 5, 5, 5, 5, 5, 5, + 87, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 284, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 285, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 32, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 95, 0, 0 +}; + +static RE_UINT8 re_alphanumeric_table_3[] = { + 0, 0, 0, 0, 0, 0, 255, 3, 254, 255, 255, 7, 0, 4, 32, 4, + 255, 255, 127, 255, 255, 255, 255, 255, 195, 255, 3, 0, 31, 80, 0, 0, + 32, 0, 0, 0, 248, 255, 223, 188, 64, 215, 255, 255, 251, 255, 255, 255, + 255, 255, 191, 255, 3, 252, 255, 255, 255, 255, 254, 255, 255, 255, 127, 2, + 255, 1, 0, 0, 0, 0, 255, 191, 182, 0, 255, 255, 255, 135, 7, 0, + 0, 0, 255, 7, 255, 255, 255, 254, 255, 195, 255, 255, 255, 255, 239, 31, + 254, 225, 255, 159, 0, 0, 255, 255, 0, 224, 255, 255, 255, 255, 3, 0, + 255, 7, 48, 4, 255, 255, 255, 252, 255, 31, 0, 0, 255, 255, 255, 1, + 255, 7, 255, 255, 255, 126, 128, 0, 255, 3, 240, 255, 248, 3, 255, 255, + 255, 255, 255, 239, 255, 223, 225, 255, 207, 255, 254, 255, 239, 159, 249, 255, + 255, 253, 197, 227, 159, 89, 128, 176, 207, 255, 3, 16, 238, 135, 249, 255, + 255, 253, 109, 195, 135, 25, 2, 94, 192, 255, 63, 0, 238, 191, 251, 255, + 255, 253, 237, 227, 191, 27, 1, 0, 207, 255, 0, 30, 238, 159, 249, 255, + 159, 25, 192, 176, 207, 255, 2, 0, 236, 199, 61, 214, 24, 199, 255, 195, + 199, 29, 129, 0, 192, 255, 0, 0, 255, 223, 253, 255, 255, 253, 255, 227, + 223, 29, 96, 39, 207, 255, 0, 0, 239, 223, 253, 255, 255, 253, 239, 227, + 223, 29, 96, 96, 207, 255, 14, 0, 255, 255, 255, 231, 223, 93, 240, 128, + 207, 255, 0, 252, 238, 255, 127, 252, 255, 255, 251, 47, 127, 128, 95, 255, + 192, 255, 12, 0, 254, 255, 255, 255, 255, 255, 255, 7, 127, 32, 255, 3, + 214, 247, 255, 255, 175, 255, 255, 59, 95, 32, 255, 243, 1, 0, 0, 0, + 255, 3, 0, 0, 255, 254, 255, 255, 255, 31, 254, 255, 15, 255, 255, 254, + 255, 255, 255, 31, 255, 255, 127, 249, 255, 3, 255, 255, 255, 255, 255, 63, + 191, 32, 255, 255, 255, 255, 255, 247, 255, 61, 127, 61, 255, 61, 255, 255, + 255, 255, 61, 127, 61, 255, 127, 255, 255, 255, 61, 255, 255, 255, 0, 0, + 255, 255, 63, 63, 255, 159, 255, 255, 255, 199, 255, 1, 255, 255, 15, 128, + 255, 255, 15, 0, 255, 223, 13, 0, 255, 255, 207, 255, 255, 1, 128, 16, + 255, 255, 63, 0, 255, 255, 255, 127, 255, 15, 255, 1, 192, 255, 255, 255, + 255, 63, 31, 0, 255, 15, 255, 255, 255, 3, 255, 3, 255, 255, 255, 15, + 254, 255, 31, 0, 128, 0, 0, 128, 1, 112, 0, 0, 255, 255, 239, 255, + 239, 31, 255, 3, 255, 243, 255, 255, 191, 255, 3, 0, 255, 255, 127, 0, + 255, 227, 255, 255, 0, 222, 111, 4, 0, 0, 248, 255, 255, 255, 31, 0, + 63, 63, 255, 170, 255, 255, 223, 95, 220, 31, 207, 15, 255, 31, 220, 31, + 0, 0, 2, 128, 0, 0, 255, 31, 132, 252, 47, 62, 80, 189, 255, 243, + 224, 67, 0, 0, 0, 0, 192, 255, 31, 120, 12, 0, 255, 128, 0, 0, + 127, 127, 127, 127, 0, 128, 0, 0, 224, 0, 0, 0, 254, 3, 62, 31, + 255, 255, 127, 224, 224, 255, 255, 255, 255, 127, 0, 0, 255, 31, 255, 255, + 255, 15, 0, 0, 255, 127, 240, 143, 0, 0, 128, 255, 252, 255, 255, 255, + 255, 249, 255, 255, 255, 63, 235, 31, 0, 0, 252, 255, 191, 255, 255, 255, + 255, 0, 0, 0, 47, 0, 255, 3, 0, 0, 252, 232, 255, 255, 7, 0, + 255, 255, 247, 255, 0, 128, 255, 3, 255, 63, 255, 3, 255, 255, 127, 252, + 5, 0, 0, 56, 255, 255, 60, 0, 126, 126, 126, 0, 127, 127, 255, 255, + 255, 7, 255, 3, 15, 0, 255, 255, 127, 248, 255, 255, 255, 63, 255, 255, + 255, 255, 255, 3, 127, 0, 248, 224, 255, 253, 127, 95, 219, 255, 255, 255, + 255, 255, 252, 255, 0, 0, 255, 15, 0, 0, 223, 255, 252, 252, 252, 28, + 255, 239, 255, 255, 127, 255, 255, 183, 255, 63, 255, 63, 255, 255, 1, 0, + 15, 255, 62, 0, 255, 255, 15, 255, 255, 0, 255, 255, 15, 0, 255, 247, + 255, 247, 183, 255, 251, 255, 251, 27, 255, 255, 253, 7, 63, 253, 255, 255, + 255, 255, 191, 145, 255, 255, 55, 0, 255, 255, 255, 192, 111, 240, 239, 254, + 31, 0, 0, 0, 255, 0, 255, 3, 63, 130, 255, 255, 63, 0, 0, 0, + 255, 27, 3, 0, 28, 0, 0, 0, 0, 0, 0, 16, 128, 0, 255, 255, + 3, 0, 0, 0, 192, 255, 62, 0, 4, 0, 255, 255, 255, 1, 255, 3, + 255, 255, 199, 255, 240, 0, 255, 255, 255, 255, 71, 0, 30, 192, 255, 23, + 255, 255, 251, 255, 255, 255, 159, 192, 127, 189, 255, 191, 255, 1, 255, 255, + 159, 25, 129, 224, 15, 0, 0, 0, 255, 75, 255, 255, 165, 55, 10, 0, + 187, 7, 255, 131, 179, 0, 255, 3, 255, 255, 63, 127, 0, 0, 0, 63, + 17, 0, 255, 3, 255, 255, 63, 1, 127, 0, 0, 0, 255, 3, 0, 128, + 127, 242, 111, 255, 255, 255, 191, 153, 7, 0, 255, 3, 255, 252, 255, 255, + 26, 0, 0, 0, 255, 255, 231, 127, 255, 255, 255, 32, 1, 0, 255, 3, + 255, 253, 255, 255, 255, 255, 127, 127, 255, 254, 127, 0, 127, 251, 255, 255, + 255, 255, 127, 180, 203, 0, 255, 3, 191, 253, 255, 255, 255, 127, 123, 1, + 255, 255, 253, 255, 255, 255, 255, 199, 0, 0, 1, 0, 126, 0, 0, 0, + 255, 127, 255, 3, 255, 63, 0, 0, 15, 0, 255, 3, 248, 255, 255, 224, + 255, 31, 255, 3, 255, 135, 255, 255, 255, 128, 255, 255, 11, 0, 3, 0, + 255, 255, 255, 0, 0, 0, 0, 128, 0, 0, 239, 111, 7, 0, 4, 0, + 0, 0, 39, 0, 255, 7, 255, 31, 255, 1, 255, 67, 255, 255, 223, 255, + 255, 255, 255, 223, 100, 222, 255, 235, 239, 255, 255, 255, 191, 231, 223, 223, + 255, 255, 255, 123, 95, 252, 253, 255, 63, 255, 255, 255, 253, 255, 255, 247, + 255, 127, 255, 255, 247, 207, 255, 255, 224, 7, 0, 0, 127, 255, 255, 249, + 219, 7, 255, 255, 255, 31, 128, 63, 255, 67, 0, 0, 255, 15, 255, 3, + 255, 63, 255, 7, 127, 111, 255, 127, 143, 8, 255, 3, 150, 254, 247, 10, + 132, 234, 150, 170, 150, 247, 247, 94, 255, 251, 255, 15, 238, 251, 255, 15, + 3, 0, 255, 255, 1, 0, 255, 255 +}; + +RE_UINT32 re_get_alphanumeric(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_alphanumeric_table_1[field_2]; + v = re_alphanumeric_table_2[(v << 5) | field_1]; + v = re_alphanumeric_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Any. */ +RE_UINT32 re_get_any(RE_UINT32 codepoint) { + return 1; +} + +/* ASCII_Hex_Digit. */ +RE_UINT32 re_get_ascii_hex_digit(RE_UINT32 codepoint) { + if (0x30 <= codepoint && codepoint <= 0x39) + return 1; + if (0x41 <= codepoint && codepoint <= 0x46) + return 1; + if (0x61 <= codepoint && codepoint <= 0x66) + return 1; + + return 0; +} + +/* Bidi_Class. */ +static RE_UINT8 re_bidi_class_table_1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 13, + 13, 13, 13, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 15, 16, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 17, 18, 18, 13, 13, 13, 13, 13, 13, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 18, 31, 13, 32, 13, 13, + 33, 34, 18, 18, 18, 18, 18, 18, 35, 18, 36, 37, 13, 13, 13, 13, + 13, 38, 13, 39, 18, 18, 18, 18, 18, 18, 18, 40, 41, 18, 18, 42, + 18, 18, 18, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 56, 13, 13, 13, 57, 58, 13, + 13, 13, 13, 59, 13, 13, 13, 13, 13, 13, 60, 61, 18, 18, 62, 55, + 13, 13, 13, 13, 63, 13, 13, 13, 64, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 55, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 55, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 55, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 55, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 55, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 55, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 55, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 55, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 55, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 55, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 55, + 65, 66, 66, 66, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 55, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 67, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 67 +}; + +static RE_UINT16 re_bidi_class_table_2[] = { + 0, 1, 2, 3, 4, 5, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 8, 9, 10, 11, 11, 11, 12, 13, 14, 7, 15, + 7, 7, 7, 7, 16, 7, 7, 7, 7, 17, 18, 7, 19, 20, 21, 22, + 23, 24, 25, 26, 24, 24, 27, 28, 29, 30, 31, 24, 24, 32, 22, 33, + 34, 35, 36, 37, 38, 24, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, + 81, 82, 83, 22, 84, 85, 86, 22, 87, 88, 89, 90, 91, 92, 93, 22, + 7, 94, 95, 96, 97, 7, 98, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 99, 7, 100, 101, 102, 7, 103, 7, 104, 105, 106, 7, 7, 107, + 108, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 109, 7, 7, 110, 111, 112, 113, 114, 7, 115, 116, 117, + 118, 7, 7, 110, 119, 120, 7, 121, 122, 123, 124, 125, 7, 126, 127, 128, + 129, 7, 130, 131, 132, 133, 134, 22, 135, 136, 137, 138, 139, 140, 7, 141, + 7, 142, 143, 7, 144, 145, 146, 147, 7, 7, 7, 7, 7, 7, 11, 11, + 7, 7, 7, 7, 7, 7, 7, 7, 107, 7, 148, 149, 7, 150, 151, 152, + 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 7, 164, 128, 128, 128, + 165, 128, 128, 128, 128, 128, 128, 128, 128, 166, 7, 167, 168, 128, 128, 128, + 128, 169, 170, 128, 171, 7, 7, 172, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 173, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 7, 7, 7, 7, 7, 7, 7, 7, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 174, 175, 128, 128, 128, + 7, 7, 7, 7, 7, 7, 7, 176, 7, 98, 7, 177, 178, 179, 179, 11, + 128, 128, 180, 22, 181, 128, 128, 182, 128, 128, 128, 128, 128, 128, 183, 184, + 185, 186, 81, 7, 187, 108, 7, 188, 189, 17, 7, 7, 190, 7, 128, 191, + 192, 7, 193, 194, 7, 195, 196, 7, 7, 7, 7, 197, 7, 7, 198, 199, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 128, 128, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 200, 128, 201, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 202, 203, 7, 204, 205, 7, 7, 206, 128, 207, 7, 7, 208, 7, 209, 210, + 211, 212, 7, 213, 7, 7, 214, 215, 7, 216, 217, 105, 41, 218, 219, 220, + 7, 221, 222, 223, 7, 224, 225, 226, 227, 228, 7, 229, 7, 7, 7, 230, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 231, 232, 233, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 234, 7, 7, 235, 22, 236, 237, 238, 24, 24, 24, 239, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 240, 241, 24, 242, 24, 243, 244, + 245, 246, 247, 248, 24, 24, 24, 249, 250, 2, 2, 251, 7, 122, 252, 253, + 254, 255, 256, 22, 7, 7, 7, 257, 258, 259, 128, 128, 260, 261, 262, 263, + 22, 22, 22, 22, 105, 7, 264, 265, 7, 266, 144, 267, 268, 7, 269, 22, + 7, 7, 7, 7, 149, 270, 271, 233, 7, 272, 7, 273, 274, 275, 7, 276, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 178, 121, 277, 278, 279, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 280, 22, 22, 22, 22, 22, 22, 22, + 281, 282, 22, 22, 22, 22, 22, 283, 22, 284, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 24, 285, 286, 287, 22, 22, 22, 22, + 22, 22, 22, 288, 22, 289, 290, 291, 22, 238, 292, 22, 293, 22, 22, 22, + 294, 295, 296, 297, 139, 298, 299, 300, 41, 301, 272, 302, 139, 303, 304, 305, + 306, 307, 308, 22, 309, 270, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, + 7, 295, 320, 321, 7, 322, 323, 22, 22, 22, 22, 22, 7, 324, 325, 22, + 7, 326, 327, 328, 7, 329, 270, 330, 331, 332, 333, 22, 22, 22, 22, 22, + 7, 334, 22, 22, 22, 7, 7, 335, 336, 337, 338, 22, 22, 339, 340, 341, + 342, 343, 344, 7, 345, 346, 7, 110, 347, 22, 22, 22, 22, 22, 7, 348, + 349, 350, 351, 352, 353, 354, 22, 22, 355, 356, 357, 358, 359, 347, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 360, 361, 362, 363, 22, 22, 364, 365, 366, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 235, 22, 22, 22, + 7, 7, 7, 367, 7, 7, 7, 7, 7, 7, 330, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 262, 7, 7, 368, + 7, 7, 369, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 257, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 333, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 205, 370, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 110, 122, 371, 7, 122, 270, 372, 7, 373, 374, 375, 376, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 7, 235, 22, 22, 22, 22, + 22, 22, 7, 7, 257, 22, 22, 22, 7, 7, 377, 7, 378, 22, 22, 379, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 380, + 7, 7, 7, 7, 7, 7, 121, 381, 382, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 383, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 384, 385, 386, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 233, 22, 22, 22, 22, 22, 22, 22, 22, + 7, 7, 7, 387, 388, 389, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 128, 128, 128, 128, 128, 128, 166, 390, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 182, 22, 22, 11, 391, 392, 7, 7, 7, 330, 22, + 7, 7, 7, 7, 7, 7, 7, 121, 7, 393, 7, 394, 395, 396, 7, 397, + 128, 128, 398, 22, 22, 22, 276, 276, 128, 128, 399, 110, 22, 22, 22, 22, + 7, 7, 400, 7, 401, 402, 403, 7, 404, 405, 406, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 407, 408, 188, 409, 409, 410, 410, 411, 411, 412, 413, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 11, 414, 11, 415, 416, 417, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 122, 418, 22, 22, 22, 22, 22, 22, + 419, 420, 7, 421, 422, 22, 22, 22, 7, 423, 424, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 262, 425, 7, 426, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 262, 427, 22, 22, 22, 22, 22, 22, 262, 428, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 429, + 22, 22, 22, 22, 22, 22, 430, 22, 22, 22, 431, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 432, 24, 433, 22, 22, 434, 435, 22, 22, 22, 22, 22, 22, + 436, 437, 438, 439, 440, 441, 22, 442, 22, 22, 22, 22, 22, 22, 22, 22, + 128, 443, 128, 128, 182, 444, 445, 183, 446, 410, 7, 447, 7, 448, 22, 449, + 346, 233, 450, 451, 22, 22, 22, 22, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 452, 453, 128, 128, 128, 454, 128, 128, 455, 456, + 443, 128, 457, 128, 458, 459, 460, 22, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 182, 461, 462, 128, 463, 464, 128, 128, 128, 128, 465, 128, 128, 466, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 467, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 22, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 235, 7, 7, 7, 7, 7, 7, + 149, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 468, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 469, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 149, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 149, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 144, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 376, 22, 22, + 470, 470, 470, 470, 470, 470, 470, 470, 11, 11, 11, 11, 11, 11, 11, 471, + 470, 470, 470, 470, 470, 470, 470, 470, 470, 470, 470, 470, 470, 470, 470, 470, + 470, 470, 470, 470, 470, 470, 470, 470, 470, 470, 470, 470, 470, 470, 470, 470, + 470, 470, 470, 470, 470, 470, 470, 470, 470, 470, 470, 470, 470, 470, 470, 470, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 472 +}; + +static RE_UINT8 re_bidi_class_table_3[] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 2, 4, 3, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 2, + 4, 5, 5, 6, 6, 6, 5, 5, 5, 5, 5, 7, 8, 7, 8, 8, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 5, 5, 5, 5, 5, + 5, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 5, 5, 5, 5, 5, + 5, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 5, 5, 5, 5, 1, + 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 8, 5, 6, 6, 6, 6, 5, 5, 5, 5, 10, 5, 5, 1, 5, 5, + 6, 6, 9, 9, 5, 10, 5, 5, 5, 9, 10, 5, 5, 5, 5, 5, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 5, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 5, 5, 10, 10, 10, 10, 10, + 10, 10, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 10, 10, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 10, 10, 10, 10, 10, 5, 5, 5, 5, 5, 5, 5, 5, 5, 10, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 10, 10, 10, 10, 5, 5, 10, 10, 0, 0, 10, 10, 10, 10, 5, 10, + 0, 0, 0, 0, 5, 5, 10, 5, 10, 10, 10, 0, 10, 0, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 5, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 0, 0, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 5, 0, 0, 5, 5, 6, + 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 11, + 0, 11, 11, 0, 11, 11, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 12, 12, 12, 12, 12, 12, 5, 5, 13, 6, 6, 13, 8, 13, 5, 5, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 6, 12, 12, 13, 13, 13, + 11, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 11, 11, 11, 11, 11, 11, 11, 12, 5, 11, + 11, 11, 11, 11, 11, 13, 13, 11, 11, 5, 11, 11, 11, 11, 13, 13, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 13, + 13, 11, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 0, 0, 5, 5, 5, 5, 0, 0, 0, 11, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 11, 11, 11, 11, 0, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 0, 11, 11, 11, 0, 11, 11, 11, 11, 11, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 11, 11, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, + 12, 12, 0, 0, 0, 0, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 10, 11, 10, 10, 10, + 10, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 11, 10, 10, + 10, 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 11, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 10, + 10, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, + 10, 0, 10, 0, 0, 0, 10, 10, 10, 10, 0, 0, 11, 10, 10, 10, + 10, 11, 11, 11, 11, 0, 0, 10, 10, 0, 0, 10, 10, 11, 10, 0, + 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 10, 10, 0, 10, + 10, 10, 11, 11, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 6, 6, 10, 10, 10, 10, 10, 10, 10, 6, 10, 10, 11, 0, + 0, 11, 11, 10, 0, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 10, + 10, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, + 10, 0, 10, 10, 0, 10, 10, 0, 10, 10, 0, 0, 11, 0, 10, 10, + 10, 11, 11, 0, 0, 0, 0, 11, 11, 0, 0, 11, 11, 11, 0, 0, + 0, 11, 0, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 0, 10, 0, + 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 11, 11, 10, 10, 10, 11, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 11, 11, 10, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, + 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, + 10, 0, 10, 10, 0, 10, 10, 10, 10, 10, 0, 0, 11, 10, 10, 10, + 10, 11, 11, 11, 11, 11, 0, 11, 11, 10, 0, 10, 10, 11, 0, 0, + 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 11, 11, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 6, 0, 0, 0, 0, 0, 0, 0, 10, 11, 11, 11, 11, 11, 11, + 0, 11, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 10, + 10, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, + 10, 0, 10, 10, 0, 10, 10, 10, 10, 10, 0, 0, 11, 10, 10, 11, + 10, 11, 11, 11, 11, 0, 0, 10, 10, 0, 0, 10, 10, 11, 0, 0, + 0, 0, 0, 0, 0, 11, 11, 10, 0, 0, 0, 0, 10, 10, 0, 10, + 10, 10, 11, 11, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 11, 10, 0, 10, 10, 10, 10, 10, 10, 0, 0, 0, 10, 10, + 10, 0, 10, 10, 10, 10, 0, 0, 0, 10, 10, 0, 10, 0, 10, 10, + 0, 0, 0, 10, 10, 0, 0, 0, 10, 10, 10, 0, 0, 0, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 10, 10, + 11, 10, 10, 0, 0, 0, 10, 10, 10, 0, 10, 10, 10, 11, 0, 0, + 10, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 5, 5, 5, 5, 5, 5, 6, 5, 0, 0, 0, 0, 0, + 11, 10, 10, 10, 11, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, + 10, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 11, 10, 11, 11, + 11, 10, 10, 10, 10, 0, 11, 11, 11, 0, 11, 11, 11, 11, 0, 0, + 0, 0, 0, 0, 0, 11, 11, 0, 10, 10, 10, 0, 0, 10, 0, 0, + 10, 10, 11, 11, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 0, 0, 0, 0, 0, 0, 0, 10, 5, 5, 5, 5, 5, 5, 5, 10, + 10, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, + 10, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 0, 0, 11, 10, 10, 10, + 10, 10, 10, 10, 10, 0, 10, 10, 10, 0, 10, 10, 11, 11, 0, 0, + 0, 0, 0, 0, 0, 10, 10, 0, 0, 0, 0, 0, 0, 10, 10, 0, + 10, 10, 11, 11, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 0, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, + 10, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 10, 10, 10, + 10, 11, 11, 11, 11, 0, 10, 10, 10, 0, 10, 10, 10, 11, 10, 10, + 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 11, 11, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 0, 11, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 11, 0, 0, 0, 0, 10, + 10, 10, 11, 11, 11, 0, 11, 0, 10, 10, 10, 10, 10, 10, 10, 10, + 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 0, 0, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 11, 10, 10, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 6, + 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, + 0, 10, 10, 0, 10, 0, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 0, 10, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 11, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 0, 0, + 10, 10, 10, 10, 10, 0, 10, 0, 11, 11, 11, 11, 11, 11, 11, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 11, 10, 11, 10, 11, 5, 5, 5, 5, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, + 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, + 11, 11, 11, 11, 11, 10, 11, 11, 10, 10, 10, 10, 10, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 0, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 10, 10, + 10, 10, 10, 10, 10, 10, 11, 10, 10, 10, 10, 10, 10, 0, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, + 11, 10, 11, 11, 11, 11, 11, 11, 10, 11, 11, 10, 10, 11, 11, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 10, 10, 10, 10, 11, 11, + 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 11, 10, 10, 11, 11, 10, 10, 10, 10, 10, 10, 11, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 10, 10, + 10, 10, 10, 10, 10, 10, 0, 10, 0, 0, 0, 0, 0, 10, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 0, 10, 0, 10, 10, 10, 10, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 10, 10, 10, 10, 0, 0, 10, 10, 10, 10, 10, 10, 10, 0, + 10, 0, 10, 10, 10, 10, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 10, 10, 10, 10, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 11, 11, 11, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 0, 0, 10, 10, 10, 10, 10, 10, 0, 0, + 5, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 4, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 5, 5, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 11, 11, 11, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 11, 11, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, + 10, 0, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 11, 11, 10, 11, 11, 11, 11, 11, 11, 11, 10, 10, + 10, 10, 10, 10, 10, 10, 11, 10, 10, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 6, 10, 11, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 11, 11, 11, 1, 11, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 10, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, + 11, 11, 11, 10, 10, 10, 10, 11, 11, 10, 10, 10, 0, 0, 0, 0, + 10, 10, 11, 10, 10, 10, 10, 10, 10, 11, 11, 11, 0, 0, 0, 0, + 5, 0, 0, 0, 5, 5, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, + 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 11, 11, 10, 10, 11, 0, 0, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 11, 10, 11, 11, 11, 11, 11, 11, 11, 0, + 11, 10, 11, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, + 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 11, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 11, 10, 11, 11, 11, 11, 11, 10, 11, 10, 10, 10, + 10, 10, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 11, 11, 11, 11, 10, 10, 11, 11, 10, 11, 11, 11, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 11, 10, 11, 11, 10, 10, 10, 11, 10, 11, + 11, 11, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, + 11, 11, 11, 11, 10, 10, 11, 11, 0, 0, 0, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 10, 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 11, 10, 10, + 10, 10, 10, 10, 11, 10, 10, 10, 11, 11, 10, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 0, 0, 10, 10, 10, 10, 10, 10, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 0, 10, 0, 10, 0, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 5, 10, 5, + 5, 5, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 5, 5, 5, + 10, 10, 10, 10, 0, 0, 10, 10, 10, 10, 10, 10, 0, 5, 5, 5, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 5, 5, 5, + 0, 0, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 5, 5, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 1, 10, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 4, 3, 14, 15, 16, 17, 18, 8, + 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 8, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, + 1, 1, 1, 1, 1, 1, 19, 20, 21, 22, 1, 1, 1, 1, 1, 1, + 9, 10, 0, 0, 9, 9, 9, 9, 9, 9, 7, 7, 5, 5, 5, 10, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 7, 7, 5, 5, 5, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 10, 5, 5, 5, 5, 10, 5, 5, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 5, 10, 5, 5, 5, 10, 10, 10, 10, 10, 5, 5, + 5, 5, 5, 5, 10, 5, 10, 5, 10, 5, 10, 10, 10, 10, 6, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 5, 5, 10, 10, 10, 10, + 5, 5, 5, 5, 5, 10, 10, 10, 10, 10, 5, 5, 5, 5, 10, 10, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 5, 5, 5, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 7, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 10, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 10, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 10, 10, 10, 10, 10, 5, 5, 5, 5, 5, 5, 10, 10, 10, 10, 11, + 11, 11, 10, 10, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, + 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 10, + 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 0, + 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 4, 5, 5, 5, 5, 10, 10, 10, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 10, 10, + 5, 10, 10, 10, 10, 10, 5, 5, 10, 10, 10, 10, 10, 5, 5, 5, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 0, 0, 11, 11, 5, 5, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 5, 10, 10, 10, 10, + 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 5, 5, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 5, 5, 5, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 5, 5, 5, 5, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 5, 5, 5, 5, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 5, 5, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 5, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 5, 5, 5, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, + 11, 11, 11, 5, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 5, 5, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 11, 11, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 5, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, + 10, 10, 0, 10, 0, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 11, 10, 10, 10, 11, 10, 10, 10, 10, 11, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 11, 11, 10, 5, 5, 5, 5, 11, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 6, 6, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, + 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 11, 10, 10, 11, 11, 11, 11, 10, 10, 11, 11, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 10, 10, + 10, 10, 10, 10, 10, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 10, + 10, 11, 11, 10, 10, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 11, 10, 10, 10, 10, 10, 10, 10, 10, 11, 10, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 11, 10, 11, 11, 11, 10, 10, 11, 11, 10, 10, 10, 10, 10, 11, 11, + 10, 11, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 10, 10, + 10, 10, 10, 10, 10, 10, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 10, 10, 10, 10, 10, 10, 0, 0, 10, 10, 10, 10, 10, 10, 0, + 0, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 5, 5, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 11, 10, 10, 11, 10, 10, 10, 10, 11, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 11, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 5, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 5, 5, 5, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 8, 5, 8, 0, 5, 8, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, + 5, 5, 7, 7, 5, 5, 5, 0, 5, 6, 6, 5, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 1, + 0, 5, 5, 6, 6, 6, 5, 5, 5, 5, 5, 7, 8, 7, 8, 8, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 0, 0, 10, 10, 10, 10, 10, 10, 0, 0, 10, 10, 10, 10, 10, 10, + 0, 0, 10, 10, 10, 10, 10, 10, 0, 0, 10, 10, 10, 0, 0, 0, + 6, 6, 5, 5, 5, 6, 6, 0, 5, 5, 5, 5, 5, 5, 5, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 1, 1, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 0, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, + 10, 5, 10, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 10, 10, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, + 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, + 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, + 10, 10, 10, 10, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, + 10, 10, 10, 0, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, + 0, 11, 11, 11, 0, 11, 11, 0, 0, 0, 0, 0, 11, 11, 11, 11, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 11, 11, 11, 0, 0, 0, 0, 11, + 0, 0, 0, 0, 0, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, + 13, 13, 13, 13, 11, 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 0, 0, 0, 0, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 11, 11, 11, 11, 5, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 11, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 11, 11, 11, + 13, 13, 13, 13, 13, 13, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, + 0, 0, 11, 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 0, 0, + 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 11, 10, 10, 11, 11, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 11, 11, 11, 11, 10, 10, 11, 11, 10, 10, 10, 10, 10, + 10, 10, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 10, 11, 11, 11, + 11, 11, 11, 11, 11, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 11, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 10, 10, 11, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, + 11, 11, 10, 10, 11, 10, 11, 11, 10, 10, 10, 10, 10, 10, 11, 10, + 10, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 0, 10, 0, 10, 10, 10, 10, 0, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, + 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, + 11, 11, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 10, + 10, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, + 10, 0, 10, 10, 0, 10, 10, 10, 10, 10, 0, 11, 11, 10, 10, 10, + 11, 10, 10, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 10, 0, 0, + 10, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 10, 10, 10, + 10, 10, 10, 10, 0, 0, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, + 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 0, 0, 10, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 11, 11, 11, 11, 11, + 11, 0, 10, 0, 0, 10, 0, 10, 10, 10, 10, 0, 10, 10, 11, 10, + 11, 10, 11, 10, 10, 10, 0, 10, 10, 0, 0, 0, 0, 0, 0, 0, + 0, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 11, 11, 11, 10, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 11, 10, + 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 11, 11, 11, 11, 11, 11, 10, 11, 10, 10, 10, 10, 11, + 11, 10, 11, 11, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 11, 11, 11, 11, 0, 0, 10, 10, 10, 10, 11, 11, 10, 11, + 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 11, 10, 11, + 11, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 10, 11, 10, 10, + 11, 11, 11, 11, 11, 11, 10, 11, 10, 10, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 11, 10, 11, + 10, 10, 11, 11, 11, 11, 10, 11, 11, 11, 11, 11, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 10, 11, 11, 10, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, + 10, 10, 10, 10, 10, 10, 10, 0, 0, 10, 0, 0, 10, 10, 10, 10, + 10, 10, 10, 10, 0, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 0, 10, 10, 0, 0, 11, 11, 10, 11, 10, + 10, 10, 10, 11, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 11, 11, 11, 11, 0, 0, 11, 11, 10, 10, 10, 10, + 11, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 11, 11, 11, 11, 11, 11, 10, 10, 11, 11, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 11, 11, 11, 11, 11, 11, 10, 10, 11, 11, 11, 11, 10, + 10, 10, 10, 10, 10, 10, 10, 11, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 11, 11, 11, 11, 11, 11, 10, 10, 11, 11, 11, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 10, 11, 11, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 11, 11, 11, 11, 11, 11, 11, 0, 11, 11, 11, 11, 11, 11, 10, 10, + 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 0, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 0, 10, 11, 11, 11, 11, 11, 11, + 11, 10, 11, 11, 10, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 0, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 11, 11, 11, 11, 11, 11, 0, 0, 0, 11, 0, 11, 11, 0, 11, + 11, 11, 11, 11, 11, 11, 10, 11, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 0, 10, 10, 0, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, + 11, 11, 0, 10, 10, 11, 10, 11, 10, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 11, 11, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 0, 0, 0, 10, 10, + 11, 10, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, + 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, + 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 11, 11, 11, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, + 11, 11, 11, 11, 11, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, + 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 11, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 11, + 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 5, 10, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 0, + 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 10, 11, 11, 10, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 0, 0, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 11, 11, 11, 11, 11, + 11, 11, 11, 10, 10, 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 5, 5, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 11, 11, 11, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, + 0, 0, 10, 0, 0, 10, 10, 0, 0, 10, 10, 10, 10, 0, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 0, 10, 10, 10, + 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 0, 0, 10, 10, 10, + 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 0, + 10, 10, 10, 10, 10, 0, 10, 0, 0, 0, 10, 10, 10, 10, 10, 10, + 10, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 5, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 5, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 5, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 5, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 5, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 5, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, + 10, 10, 10, 10, 10, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 11, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 11, 11, 11, 11, + 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 0, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 11, 11, 11, 11, 11, + 11, 11, 0, 11, 11, 0, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 10, 10, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 6, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 10, + 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 0, 10, 10, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, + 13, 13, 13, 13, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 0, 13, 13, 0, 13, 0, 0, 13, 0, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 0, 13, 13, 13, 13, 0, 13, 0, 13, 0, 0, 0, 0, + 0, 0, 13, 0, 0, 0, 0, 13, 0, 13, 0, 13, 0, 13, 13, 13, + 0, 13, 13, 0, 13, 0, 0, 13, 0, 13, 0, 13, 0, 13, 0, 13, + 0, 13, 13, 0, 13, 0, 0, 13, 13, 13, 13, 0, 13, 13, 13, 13, + 13, 13, 13, 0, 13, 13, 13, 13, 0, 13, 13, 13, 13, 0, 13, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, + 0, 13, 13, 13, 0, 13, 13, 13, 13, 13, 0, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, + 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 5, 5, 5, 5, 5, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 5, 5, 5, 5, 5, 5, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 5, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, + 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, + 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 1, 1 +}; + +RE_UINT32 re_get_bidi_class(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = codepoint & 0x1F; + + v = re_bidi_class_table_1[field_2]; + v = re_bidi_class_table_2[(v << 5) | field_1]; + v = re_bidi_class_table_3[(v << 5) | field_0]; + + return v; +} + +/* Bidi_Control. */ +RE_UINT32 re_get_bidi_control(RE_UINT32 codepoint) { + if (codepoint == 0x061C) + return 1; + if (0x200E <= codepoint && codepoint <= 0x200F) + return 1; + if (0x202A <= codepoint && codepoint <= 0x202E) + return 1; + if (0x2066 <= codepoint && codepoint <= 0x2069) + return 1; + + return 0; +} + +/* Bidi_Mirrored. */ +static RE_UINT8 re_bidi_mirrored_table_1[] = { + 0, 1, 1, 2, 1, 3, 1, 1, 4, 5, 6, 7, 8, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +}; + +static RE_UINT8 re_bidi_mirrored_table_2[] = { + 0, 1, 2, 2, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6, 7, 8, 9, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 22, 23, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 25, 26, 27, + 28, 29, 30, 31, 32, 33, 34, 35, 0, 0, 0, 0, 0, 0, 0, 36, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 37, 38, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 41, 42, 0, 0, 0, 0, 1, 2, 43, 44, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 45, 0, 46, 0, 47, 0, 48, 0, 49, 0 +}; + +static RE_UINT8 re_bidi_mirrored_table_3[] = { + 0, 0, 0, 0, 0, 3, 0, 80, 0, 0, 0, 40, 0, 8, 0, 8, + 0, 0, 0, 60, 0, 0, 0, 24, 0, 0, 0, 6, 96, 0, 0, 0, + 0, 0, 0, 96, 0, 96, 0, 0, 1, 0, 0, 0, 30, 63, 98, 188, + 87, 248, 15, 250, 255, 31, 60, 128, 245, 239, 255, 255, 255, 159, 7, 1, + 204, 255, 255, 193, 0, 62, 195, 255, 255, 63, 255, 255, 0, 15, 0, 0, + 3, 6, 0, 0, 0, 255, 63, 0, 121, 59, 120, 112, 252, 255, 0, 0, + 248, 255, 255, 249, 253, 255, 0, 1, 63, 194, 55, 31, 58, 3, 240, 51, + 0, 252, 255, 223, 83, 122, 48, 112, 0, 0, 128, 1, 48, 188, 25, 254, + 255, 255, 255, 255, 207, 191, 255, 255, 255, 255, 127, 80, 124, 112, 136, 47, + 0, 0, 0, 64, 60, 54, 0, 48, 255, 3, 0, 0, 0, 0, 224, 31, + 0, 255, 243, 15, 0, 0, 0, 126, 48, 0, 0, 0, 0, 0, 0, 168, + 13, 0, 0, 0, 0, 0, 0, 8, 0, 0, 32, 0, 0, 128, 0, 0, + 0, 2, 0, 0, 8, 0, 0, 0 +}; + +RE_UINT32 re_get_bidi_mirrored(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_bidi_mirrored_table_1[field_2]; + v = re_bidi_mirrored_table_2[(v << 5) | field_1]; + v = re_bidi_mirrored_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Blank. */ +RE_UINT32 re_get_blank(RE_UINT32 codepoint) { + if (codepoint == 0x09) + return 1; + if (codepoint == 0x20) + return 1; + if (codepoint == 0xA0) + return 1; + if (codepoint == 0x1680) + return 1; + if (0x2000 <= codepoint && codepoint <= 0x200A) + return 1; + if (codepoint == 0x202F) + return 1; + if (codepoint == 0x205F) + return 1; + if (codepoint == 0x3000) + return 1; + + return 0; +} + +/* Block. */ +static RE_UINT8 re_block_table_1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 13, + 13, 13, 13, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 16, 17, 18, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 20, 21, 22, 23, 23, 23, 23, 23, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 40, + 40, 41, 36, 36, 36, 36, 36, 36, 42, 36, 43, 44, 45, 45, 45, 45, + 45, 45, 46, 47, 36, 36, 36, 36, 36, 36, 36, 48, 49, 36, 36, 50, + 36, 36, 36, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 36, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 64, 65, 65, 65, 66, 67, 68, + 68, 68, 68, 69, 70, 70, 70, 70, 70, 70, 71, 72, 36, 36, 73, 36, + 74, 74, 74, 74, 75, 76, 76, 76, 77, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 78, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80 +}; + +static RE_UINT16 re_block_table_2[] = { + 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, + 3, 3, 4, 5, 5, 6, 7, 7, 8, 8, 8, 9, 10, 10, 10, 10, + 11, 11, 11, 11, 11, 11, 11, 11, 12, 13, 14, 14, 15, 16, 16, 16, + 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 19, 20, 21, 21, 22, 22, + 23, 23, 24, 25, 26, 27, 27, 27, 28, 28, 28, 28, 29, 29, 29, 29, + 30, 30, 30, 30, 31, 31, 31, 31, 32, 32, 32, 32, 33, 33, 33, 33, + 34, 34, 34, 34, 35, 35, 35, 35, 36, 36, 36, 36, 37, 37, 37, 37, + 38, 38, 38, 38, 39, 39, 39, 39, 40, 40, 40, 40, 40, 40, 40, 40, + 41, 41, 41, 41, 41, 42, 42, 42, 43, 43, 43, 43, 43, 43, 43, 43, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 45, 46, 46, 46, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 48, 49, 49, 49, 50, 51, 52, 53, 54, 54, 54, 54, + 55, 55, 55, 55, 55, 56, 57, 57, 58, 58, 59, 60, 61, 61, 61, 62, + 63, 64, 64, 64, 64, 65, 66, 66, 67, 67, 67, 67, 68, 68, 69, 69, + 70, 70, 71, 72, 73, 74, 75, 76, 77, 77, 77, 77, 78, 78, 79, 79, + 80, 80, 80, 80, 80, 80, 80, 80, 81, 81, 81, 81, 81, 81, 81, 81, + 82, 82, 82, 83, 84, 85, 86, 87, 88, 88, 89, 90, 91, 92, 92, 92, + 93, 93, 93, 93, 93, 93, 93, 93, 94, 94, 94, 94, 94, 94, 94, 94, + 95, 95, 96, 97, 97, 97, 97, 97, 98, 98, 98, 98, 99, 100, 100, 100, + 101, 101, 101, 101, 101, 101, 101, 101, 102, 102, 102, 102, 102, 102, 103, 104, + 105, 105, 105, 105, 105, 105, 105, 105, 106, 106, 106, 106, 107, 107, 107, 107, + 108, 108, 108, 108, 108, 108, 108, 108, 109, 109, 109, 109, 109, 109, 109, 109, + 110, 110, 110, 111, 112, 112, 112, 112, 113, 114, 115, 115, 116, 116, 116, 117, + 118, 118, 118, 118, 119, 119, 119, 119, 120, 120, 120, 120, 120, 120, 120, 121, + 122, 122, 123, 123, 123, 124, 124, 124, 125, 126, 127, 127, 128, 129, 130, 131, + 132, 132, 132, 132, 132, 132, 132, 132, 133, 133, 133, 133, 133, 133, 133, 133, + 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, + 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, + 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 135, 135, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 138, 139, 140, 141, 142, 142, 142, 142, 142, 142, 142, 142, + 142, 142, 143, 143, 143, 144, 144, 144, 145, 146, 146, 146, 146, 146, 146, 146, + 147, 148, 149, 149, 150, 150, 150, 151, 152, 153, 154, 155, 156, 156, 156, 157, + 158, 158, 158, 159, 160, 160, 160, 161, 162, 163, 164, 165, 166, 166, 167, 167, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 169, 170, 170, + 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, + 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 172, 172, 172, 172, + 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, + 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 175, 175, 175, 175, 175, 175, 175, 175, + 175, 175, 175, 175, 175, 175, 175, 175, 176, 176, 177, 178, 178, 178, 178, 178, + 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, + 179, 180, 181, 182, 183, 183, 183, 183, 184, 184, 184, 184, 184, 184, 184, 185, + 186, 186, 186, 186, 187, 187, 187, 187, 188, 188, 189, 189, 190, 191, 192, 193, + 194, 194, 194, 194, 195, 196, 196, 197, 198, 199, 200, 201, 202, 203, 203, 194, + 204, 204, 205, 206, 207, 208, 209, 209, 210, 211, 212, 213, 214, 214, 215, 215, + 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 217, 217, 194, 194, + 218, 218, 219, 220, 221, 222, 194, 223, 224, 225, 194, 194, 226, 227, 227, 227, + 228, 228, 228, 229, 230, 194, 231, 231, 232, 232, 233, 234, 235, 236, 194, 194, + 237, 237, 238, 194, 239, 239, 239, 239, 240, 240, 241, 241, 242, 194, 194, 194, + 194, 194, 194, 243, 244, 244, 245, 245, 246, 247, 248, 249, 250, 251, 252, 253, + 254, 254, 254, 254, 255, 255, 256, 257, 258, 258, 259, 260, 261, 261, 261, 262, + 263, 263, 264, 194, 265, 266, 267, 267, 268, 268, 268, 268, 269, 269, 269, 269, + 270, 270, 270, 270, 271, 271, 271, 194, 194, 194, 194, 194, 272, 272, 272, 272, + 273, 273, 273, 274, 275, 275, 276, 277, 278, 278, 279, 194, 194, 194, 194, 194, + 280, 280, 281, 194, 194, 282, 282, 282, 283, 283, 283, 194, 194, 284, 284, 284, + 285, 285, 286, 287, 287, 288, 289, 289, 290, 290, 290, 194, 194, 194, 291, 291, + 292, 292, 292, 293, 294, 294, 194, 194, 295, 295, 295, 296, 296, 297, 194, 194, + 194, 194, 194, 194, 194, 194, 194, 298, 299, 299, 299, 194, 194, 300, 301, 301, + 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, + 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, + 303, 303, 303, 303, 304, 304, 304, 304, 304, 304, 305, 194, 194, 194, 194, 194, + 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, + 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, + 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, + 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, + 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 306, 307, 307, 307, + 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, + 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, + 308, 309, 310, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, + 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, + 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, + 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, + 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, + 312, 312, 312, 312, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, + 194, 194, 194, 194, 194, 194, 194, 194, 313, 313, 194, 194, 194, 194, 194, 194, + 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, + 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 315, 316, 317, 317, 318, 319, 320, 320, 320, 320, 321, 194, 194, 194, + 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 322, 322, 194, 194, 194, 194, + 194, 194, 323, 323, 323, 194, 194, 194, 324, 324, 324, 324, 324, 194, 194, 325, + 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, + 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, + 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, + 327, 327, 327, 327, 327, 327, 327, 327, 328, 328, 328, 328, 328, 328, 328, 328, + 328, 328, 328, 328, 328, 328, 328, 328, 329, 329, 329, 329, 194, 194, 194, 194, + 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, + 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, + 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 330, + 331, 331, 331, 331, 331, 331, 331, 331, 332, 333, 334, 335, 336, 336, 336, 336, + 336, 336, 336, 336, 336, 336, 336, 336, 194, 194, 194, 194, 194, 194, 194, 194, + 337, 337, 337, 337, 337, 338, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, + 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, + 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, + 339, 339, 339, 339, 339, 339, 194, 194, 340, 340, 340, 340, 340, 340, 341, 194, + 342, 342, 342, 342, 342, 342, 342, 342, 343, 343, 343, 343, 343, 343, 343, 343, + 344, 344, 345, 194, 194, 194, 346, 347, 348, 348, 348, 349, 194, 194, 194, 194, + 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, + 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, + 351, 351, 351, 351, 351, 351, 351, 351, 351, 351, 351, 351, 351, 351, 351, 351, + 351, 351, 351, 351, 351, 352, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, + 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, + 194, 194, 194, 194, 194, 194, 194, 194, 353, 353, 353, 353, 353, 353, 353, 353, + 354, 355, 356, 356, 357, 194, 194, 194, 358, 358, 359, 194, 194, 194, 194, 194, + 194, 194, 194, 194, 360, 361, 362, 362, 194, 194, 194, 194, 194, 194, 194, 194, + 194, 194, 194, 194, 194, 194, 363, 364, 194, 194, 194, 194, 194, 194, 365, 366, + 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 367, + 368, 368, 368, 368, 368, 368, 368, 194, 369, 369, 369, 194, 194, 194, 194, 194, + 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, + 194, 194, 194, 370, 371, 371, 194, 194, 372, 372, 373, 194, 194, 194, 194, 194, + 374, 374, 374, 374, 374, 374, 374, 374, 194, 194, 194, 194, 194, 194, 194, 194, + 375, 376, 377, 377, 377, 378, 378, 378, 379, 379, 379, 379, 379, 379, 379, 379, + 380, 380, 380, 380, 380, 380, 380, 380, 381, 381, 381, 381, 381, 381, 381, 381, + 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, + 382, 382, 383, 384, 385, 385, 385, 385, 386, 386, 386, 386, 387, 387, 387, 387, + 388, 388, 388, 388, 388, 388, 388, 388, 389, 389, 389, 389, 389, 389, 389, 389, + 390, 390, 390, 391, 392, 392, 392, 392, 393, 393, 393, 393, 393, 393, 393, 393, + 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, + 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, + 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, + 394, 394, 394, 394, 394, 394, 394, 194, 395, 395, 395, 395, 395, 395, 395, 395, + 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, + 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, + 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, + 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 396, 396, 396, 396, 396, 396, + 396, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, + 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, + 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, + 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, + 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, + 397, 397, 397, 397, 397, 398, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, + 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, + 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, + 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, + 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 400, + 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, + 401, 401, 401, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, + 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, + 402, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, + 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, + 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, + 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, + 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 404, 405, 405, 405, 405, 405, + 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, + 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, + 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, + 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 406, 194, 194, + 407, 407, 407, 407, 194, 194, 194, 194, 408, 408, 408, 408, 408, 408, 408, 409, + 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, + 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, + 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, 410, + 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, + 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411, 411 +}; + +static RE_UINT16 re_block_table_3[] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, + 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, + 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, + 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, + 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, + 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, + 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, + 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, + 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, + 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, + 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, + 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, + 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, + 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, + 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, + 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, + 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, + 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, + 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, + 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, + 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, + 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, + 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, + 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, + 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, + 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, + 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, + 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, + 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, + 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, + 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, + 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, + 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, + 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, + 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, + 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, + 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, + 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, + 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, + 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, + 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, + 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, + 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, + 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, + 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, + 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, + 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, + 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, + 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, + 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, + 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, + 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, + 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, + 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, + 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, + 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, + 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, + 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, + 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, + 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, + 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, + 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, + 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, + 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, + 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, + 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, + 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, + 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, + 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, + 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, + 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, + 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, + 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, + 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, + 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, + 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, + 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, + 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, + 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, + 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, + 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, + 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, + 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, + 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, + 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, + 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, + 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, + 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, + 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, + 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, + 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, + 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, + 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, + 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, + 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, + 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, + 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, + 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, + 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, + 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, + 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, + 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, + 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, + 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, + 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, + 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, + 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, + 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, + 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, + 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, + 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, + 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, + 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, + 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, + 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, + 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, + 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, + 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, + 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, + 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, + 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, + 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, + 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, + 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, + 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, + 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, + 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, + 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, + 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, + 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, + 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, + 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, + 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, + 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, + 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, + 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, + 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, + 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, + 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, + 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, + 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, + 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, + 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, + 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, + 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, + 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, + 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, + 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, + 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, + 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, + 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, + 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, + 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, + 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, + 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, + 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, + 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, + 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, + 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, + 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, + 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, + 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, + 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, + 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, + 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, + 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, + 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, + 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, + 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, + 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, + 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, + 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, + 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, + 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, + 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, + 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, + 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, + 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, + 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, + 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, + 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, + 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, + 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, + 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, + 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, + 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, + 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, + 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, + 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, + 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, + 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, + 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, + 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, + 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, + 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, + 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, + 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, + 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, + 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, + 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, + 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, + 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, + 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, + 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, + 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, + 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, + 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, + 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, + 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, + 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, + 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, + 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, + 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, + 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, + 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, + 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, + 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, + 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, + 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, + 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, + 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, + 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, + 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, + 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, + 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, + 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, + 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, + 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, + 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, + 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, + 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, + 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, + 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, + 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, + 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, + 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, + 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, + 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, + 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, + 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, + 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, + 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, + 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, + 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, + 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, + 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, + 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, + 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, + 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, + 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, + 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, + 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, + 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, + 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, + 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, + 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, + 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, + 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, + 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, + 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, + 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, + 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, + 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, + 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, + 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, + 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, + 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, + 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, + 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, + 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, + 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, + 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, + 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, + 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, + 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, + 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, + 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, + 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, + 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, + 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, + 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, + 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, + 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, + 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, + 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, + 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, + 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, + 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, + 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, + 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, + 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, + 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, + 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, + 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, + 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, + 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, + 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, + 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, + 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, + 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, + 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, + 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, + 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, + 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, + 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, + 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, + 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, + 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, + 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, + 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, + 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, + 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, + 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, + 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, + 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, + 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, + 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, + 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, + 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, + 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, + 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, + 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, + 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, + 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, + 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, + 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, + 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, + 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, + 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, + 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, + 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, + 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, + 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, + 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, + 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, + 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, + 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, + 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, + 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, + 292, 292, 292, 292, 292, 292, 292, 292, 292, 292, 292, 292, 292, 292, 292, 292, + 292, 292, 292, 292, 292, 292, 292, 292, 292, 292, 292, 292, 292, 292, 292, 292, + 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, + 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, + 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, + 297, 297, 297, 297, 297, 297, 297, 297, 297, 297, 297, 297, 297, 297, 297, 297, + 297, 297, 297, 297, 297, 297, 297, 297, 297, 297, 297, 297, 297, 297, 297, 297, + 297, 297, 297, 297, 297, 297, 297, 297, 297, 297, 297, 297, 297, 297, 297, 297, + 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, + 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, + 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, + 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, + 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, + 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, + 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, + 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, + 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, + 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, + 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, + 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, + 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, + 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, + 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, + 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, + 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, + 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, + 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, + 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, + 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, + 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, + 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, + 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, + 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, + 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, + 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, + 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, + 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, + 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, + 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, + 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, + 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, + 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, + 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, + 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, + 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, + 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, + 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, + 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, + 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, + 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, + 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, + 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, + 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, + 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, + 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, + 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, + 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, + 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, + 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, + 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, + 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, + 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, + 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, + 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, + 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, + 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, + 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, + 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, + 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, + 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, + 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, + 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, + 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, + 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, + 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, + 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, + 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, + 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, + 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, + 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, + 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, + 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, + 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, + 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, + 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, + 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, + 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, + 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, + 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, + 336, 336, 336, 336, 336, 336, 336, 336, 336, 336, 336, 336, 336, 336, 336, 336, + 336, 336, 336, 336, 336, 336, 336, 336, 336, 336, 336, 336, 336, 336, 336, 336, + 336, 336, 336, 336, 336, 336, 336, 336, 336, 336, 336, 336, 336, 336, 336, 336, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, + 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, + 338, 338, 338, 338, 338, 338, 338, 338, 338, 338, 338, 338, 338, 338, 338, 338, + 338, 338, 338, 338, 338, 338, 338, 338, 338, 338, 338, 338, 338, 338, 338, 338 +}; + +RE_UINT32 re_get_block(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = codepoint & 0x1F; + + v = re_block_table_1[field_2]; + v = re_block_table_2[(v << 5) | field_1]; + v = re_block_table_3[(v << 5) | field_0]; + + return v; +} + +/* Canonical_Combining_Class. */ +static RE_UINT8 re_canonical_combining_class_table_1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 11, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 12, 13, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 14, 15, + 16, 9, 17, 18, 19, 20, 21, 22, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 23, 9, 24, 25, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 26, + 9, 9, 9, 9, 27, 9, 9, 9, 28, 29, 30, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 +}; + +static RE_UINT8 re_canonical_combining_class_table_2[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 7, 8, 0, + 9, 0, 10, 11, 0, 0, 12, 13, 14, 15, 16, 0, 0, 0, 0, 17, + 18, 19, 20, 0, 21, 0, 22, 23, 0, 24, 25, 0, 0, 24, 26, 27, + 0, 24, 26, 0, 0, 24, 26, 0, 0, 24, 26, 0, 0, 0, 26, 0, + 0, 24, 28, 0, 0, 24, 26, 0, 0, 29, 26, 0, 0, 0, 30, 0, + 0, 31, 32, 0, 0, 33, 34, 0, 35, 36, 0, 37, 38, 0, 39, 0, + 0, 40, 0, 0, 41, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 43, 44, 0, 0, 0, 0, 45, 0, + 0, 0, 0, 0, 0, 46, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, + 48, 0, 0, 49, 0, 50, 51, 0, 0, 52, 53, 54, 0, 55, 0, 56, + 0, 57, 0, 0, 0, 0, 58, 59, 0, 0, 0, 0, 0, 0, 60, 61, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 62, 63, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 65, 0, 0, 0, 66, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 67, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 69, 70, 0, 0, 71, 0, 0, 0, 0, 0, 0, 0, 0, + 72, 73, 0, 0, 0, 0, 53, 74, 0, 75, 76, 0, 0, 77, 78, 0, + 0, 0, 0, 0, 0, 79, 80, 81, 0, 0, 0, 0, 0, 0, 0, 26, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, + 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 86, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 87, 88, 0, 0, 0, 0, 0, 89, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 0, 91, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 92, 0, 93, 0, 0, 94, 0, 95, 0, 0, 0, + 0, 0, 72, 96, 0, 97, 0, 0, 98, 99, 0, 77, 0, 0, 100, 0, + 0, 101, 0, 0, 0, 0, 0, 102, 0, 103, 26, 104, 0, 0, 105, 0, + 0, 0, 106, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 65, 108, 0, + 0, 65, 0, 0, 0, 109, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 0, 97, 0, 0, 0, 0, 0, 0, 0, 111, 112, 0, 0, 0, 0, 78, + 0, 44, 113, 0, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 115, 0, 116, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 119, 0, 120, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, + 0, 0, 0, 0, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 124, 125, 0, 0, + 0, 0, 126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 127, 128, 0, 0, 129, 0, 0, 0, 0, 120, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 130, 0, 131, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 132, 0, 0, 0, 0, 0, 0, 0, 133, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 134, 0, 0, 0, 135, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_canonical_combining_class_table_3[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 2, 3, 3, 3, 3, 2, 4, 3, 3, 3, 3, + 3, 5, 5, 3, 3, 3, 3, 5, 5, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 6, 6, 6, 6, 6, 3, 3, 3, 3, 1, 1, 1, + 1, 1, 1, 1, 1, 7, 1, 3, 3, 3, 1, 1, 1, 3, 3, 0, + 1, 1, 1, 3, 3, 3, 3, 1, 2, 3, 3, 1, 8, 9, 9, 8, + 9, 9, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3, 1, 1, 1, 1, 3, 1, 1, 1, 10, 3, 1, 1, 1, 1, + 1, 1, 3, 3, 3, 3, 3, 3, 1, 1, 3, 1, 1, 10, 11, 1, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 21, 22, 23, 24, 0, 25, + 0, 26, 27, 0, 1, 3, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 28, 29, 30, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 32, 33, 28, 29, + 30, 34, 35, 1, 1, 3, 3, 1, 1, 1, 1, 1, 3, 1, 1, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, + 1, 1, 1, 3, 1, 0, 0, 1, 1, 0, 3, 1, 1, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 37, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 3, 1, 1, 3, 1, 1, 3, 3, 3, 1, 3, 3, 1, 3, 1, + 1, 1, 3, 1, 3, 1, 3, 1, 3, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 3, 3, 3, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 3, + 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 3, 1, 1, 3, 1, 1, 3, 1, 1, 1, 3, 3, 3, + 31, 32, 33, 1, 1, 1, 3, 1, 1, 3, 3, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 0, 0, + 0, 1, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 0, 0, + 0, 0, 0, 0, 0, 40, 41, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 39, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 42, 42, 39, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 43, 43, 43, 43, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 44, 44, 39, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 45, 45, 45, 45, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 3, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 46, 47, 0, 48, 0, 0, 0, 0, 0, 47, 47, 47, 47, 0, 0, + 47, 0, 1, 1, 39, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 38, 0, 39, 39, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 39, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 1, 3, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 3, 0, 0, 0, 0, 0, 0, 0, + 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 1, 1, 3, 0, 3, + 3, 1, 1, 3, 3, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 39, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 39, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 0, 6, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, + 1, 0, 6, 6, 6, 6, 6, 6, 6, 0, 0, 0, 0, 3, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 9, 49, 3, + 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 2, 11, 11, 3, 50, 1, 8, 3, 1, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 6, 6, 1, 1, 1, 1, 6, 6, 6, 1, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 6, 6, 1, 3, 1, 6, 6, 3, 3, 3, 3, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 11, 2, 10, 51, 51, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 52, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 1, 1, 3, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 0, + 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, + 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 6, 3, 0, 0, 0, 0, 39, + 0, 0, 0, 0, 0, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, + 0, 0, 0, 0, 0, 0, 3, 3, 1, 1, 1, 3, 1, 3, 3, 3, + 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 3, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 38, 0, 0, 0, 0, 0, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 39, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 39, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 39, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 38, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 39, + 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 39, 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 39, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 39, 38, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 39, 0, + 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 39, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 0, 0, 0, 0, 0, 0, + 0, 0, 38, 0, 39, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 39, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 39, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 54, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 4, 4, 6, 6, 6, 0, 0, 0, 55, 4, 4, + 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, + 3, 3, 3, 0, 0, 1, 1, 1, 1, 1, 3, 3, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 3, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 38, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +RE_UINT32 re_get_canonical_combining_class(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = codepoint & 0x1F; + + v = re_canonical_combining_class_table_1[field_2]; + v = re_canonical_combining_class_table_2[(v << 5) | field_1]; + v = re_canonical_combining_class_table_3[(v << 5) | field_0]; + + return v; +} + +/* Cased. */ +static RE_UINT8 re_cased_table_1[] = { + 0, 1, 2, 2, 3, 2, 2, 4, 5, 6, 2, 7, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 8, 9, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 10, 11, + 2, 12, 2, 13, 2, 2, 14, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 15, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 16, 2, 17, 18, 2, 19, 2, 20, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 +}; + +static RE_UINT8 re_cased_table_2[] = { + 0, 0, 1, 1, 0, 2, 3, 3, 4, 4, 4, 4, 4, 5, 6, 4, + 4, 4, 4, 4, 7, 8, 9, 10, 0, 0, 11, 12, 13, 14, 4, 15, + 4, 4, 4, 4, 16, 4, 4, 4, 4, 17, 18, 4, 19, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 4, 20, 5, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 21, + 0, 0, 0, 0, 22, 23, 0, 0, 4, 4, 4, 4, 4, 4, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 21, 4, 24, 25, 4, 26, 27, 28, + 0, 0, 0, 29, 30, 0, 0, 0, 31, 32, 33, 4, 34, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 35, 4, 36, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 37, 4, 38, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 39, 25, 0, 0, 0, 0, 40, 4, 4, 41, 4, 42, 43, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 5, 45, 4, 4, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 46, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, + 4, 4, 47, 0, 0, 44, 48, 49, 0, 0, 0, 50, 51, 52, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 54, 0, 0, + 0, 0, 0, 0, 4, 55, 4, 55, 0, 0, 44, 56, 57, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 58, 4, 59, 60, 61, 4, 62, 63, 64, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 65, 66, 5, 58, 58, 67, 67, 68, 68, 69, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 70, 71, 0, 0, 0, 0, 0, 0, + 0, 44, 4, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 72, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 45, 45, 36, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_cased_table_3[] = { + 0, 0, 0, 0, 254, 255, 255, 7, 0, 4, 32, 4, 255, 255, 127, 255, + 255, 255, 255, 255, 255, 255, 255, 247, 240, 255, 255, 255, 255, 255, 239, 255, + 255, 255, 255, 1, 3, 0, 0, 0, 31, 0, 0, 0, 32, 0, 0, 0, + 0, 0, 207, 188, 64, 215, 255, 255, 251, 255, 255, 255, 255, 255, 191, 255, + 3, 252, 255, 255, 255, 255, 254, 255, 255, 255, 127, 0, 255, 1, 0, 0, + 191, 32, 255, 255, 255, 255, 63, 63, 255, 7, 255, 255, 255, 255, 255, 231, + 63, 63, 255, 170, 255, 255, 255, 63, 255, 255, 223, 95, 220, 31, 207, 15, + 255, 31, 220, 31, 0, 0, 2, 128, 0, 0, 255, 31, 132, 252, 47, 62, + 80, 189, 31, 242, 224, 67, 0, 0, 24, 0, 0, 0, 0, 0, 192, 255, + 255, 3, 0, 0, 31, 120, 12, 0, 191, 32, 0, 0, 255, 63, 0, 0, + 252, 255, 255, 255, 255, 120, 255, 255, 255, 63, 235, 31, 0, 0, 124, 7, + 0, 0, 255, 255, 255, 3, 255, 255, 127, 0, 248, 0, 255, 255, 0, 0, + 255, 255, 15, 255, 255, 255, 255, 15, 0, 0, 255, 247, 255, 247, 183, 255, + 251, 255, 251, 27, 185, 255, 255, 255, 255, 255, 253, 7, 255, 255, 7, 0, + 63, 0, 255, 255, 63, 0, 0, 0, 255, 255, 223, 255, 255, 255, 255, 223, + 100, 222, 255, 235, 239, 255, 255, 255, 191, 231, 223, 223, 255, 255, 255, 123, + 95, 252, 253, 255, 63, 255, 255, 255, 253, 255, 255, 247, 255, 127, 255, 255, + 255, 253, 255, 255, 247, 15, 0, 0, 255, 251, 255, 127, 224, 7, 0, 0, + 15, 0, 0, 0 +}; + +RE_UINT32 re_get_cased(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_cased_table_1[field_2]; + v = re_cased_table_2[(v << 5) | field_1]; + v = re_cased_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Case_Ignorable. */ +static RE_UINT8 re_case_ignorable_table_1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 11, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 12, 13, 14, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 9, 9, 9, 9, 9, 25, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 26, 9, 27, 28, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 29, 9, 9, 9, 30, + 9, 9, 9, 31, 32, 9, 33, 9, 34, 35, 36, 9, 37, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 38, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 +}; + +static RE_UINT8 re_case_ignorable_table_2[] = { + 0, 1, 2, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 5, 6, 6, 6, 6, 6, 7, 8, 0, 0, 0, + 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 10, 0, 11, 12, 13, 14, + 15, 0, 16, 17, 0, 0, 18, 19, 20, 5, 21, 0, 0, 22, 0, 23, + 24, 25, 26, 0, 27, 0, 28, 6, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 34, 38, 39, 37, 34, 40, 41, 33, 42, 43, 44, 45, 0, 46, 0, + 47, 48, 49, 44, 33, 42, 50, 44, 51, 52, 35, 44, 33, 0, 53, 0, + 0, 54, 55, 0, 0, 56, 57, 0, 58, 59, 0, 60, 61, 62, 63, 0, + 0, 64, 65, 66, 67, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 69, 70, 70, 70, 0, 71, 72, 0, + 73, 0, 74, 0, 75, 76, 0, 0, 0, 77, 0, 0, 0, 0, 0, 0, + 78, 0, 79, 80, 0, 81, 82, 0, 83, 84, 45, 85, 51, 86, 0, 87, + 0, 88, 0, 89, 0, 0, 90, 91, 0, 92, 6, 93, 94, 6, 6, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 96, 97, + 98, 99, 0, 100, 101, 0, 5, 102, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 103, 0, 0, 0, 104, 0, 0, 0, 105, 0, 0, 0, 6, + 0, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 107, 108, 0, 0, 109, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 89, 0, 0, 0, 0, 0, 0, 0, 0, + 112, 0, 0, 113, 114, 0, 0, 115, 6, 51, 0, 17, 116, 0, 0, 117, + 118, 119, 0, 0, 0, 0, 120, 121, 0, 122, 123, 0, 29, 124, 106, 75, + 0, 125, 126, 127, 0, 128, 129, 130, 0, 0, 94, 131, 0, 0, 0, 132, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 133, 29, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 134, 135, 136, 0, 0, 0, 0, 137, 1, 2, 3, 17, 138, 0, 0, 139, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, + 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 141, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142, 143, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 144, 145, 0, 0, 0, 0, 0, 75, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 146, 147, 148, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 149, 0, 114, 0, 0, 22, 0, 150, 0, 0, 0, + 33, 151, 152, 153, 51, 154, 155, 0, 29, 156, 0, 157, 51, 158, 159, 0, + 0, 160, 33, 0, 0, 0, 137, 161, 51, 52, 3, 162, 0, 94, 163, 37, + 0, 151, 164, 0, 0, 165, 166, 0, 0, 0, 0, 0, 0, 167, 168, 0, + 0, 169, 3, 0, 0, 170, 0, 0, 95, 171, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 173, 74, 0, 0, 0, 174, 3, + 175, 176, 177, 0, 178, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 179, 0, 0, 133, 180, 0, 0, 0, 181, 182, 0, 183, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 184, 51, 141, 185, 0, 0, 0, 0, 0, + 0, 5, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 138, 187, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 188, 0, 189, 83, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 149, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 0, 190, 0, 0, 191, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, + 0, 0, 0, 0, 193, 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 194, 152, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 196, 197, 0, 0, + 0, 0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 199, 6, 200, 201, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 203, 204, 6, 25, 106, 0, 0, 0, 0, 205, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 147, 0, 206, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0, 0, 0, 207, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 189, 0, 0, 0, 208, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, + 33, 6, 6, 6, 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, 135, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_case_ignorable_table_3[] = { + 0, 0, 0, 0, 128, 64, 0, 4, 0, 0, 0, 64, 1, 0, 0, 0, + 0, 161, 144, 1, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 48, 4, + 176, 0, 0, 0, 248, 3, 0, 0, 0, 0, 0, 130, 0, 0, 254, 255, + 255, 255, 255, 191, 182, 0, 0, 0, 0, 0, 16, 0, 63, 0, 255, 23, + 1, 248, 255, 255, 0, 0, 1, 0, 0, 0, 192, 191, 255, 61, 0, 0, + 0, 128, 2, 0, 255, 7, 0, 0, 192, 255, 1, 0, 0, 248, 63, 36, + 0, 0, 192, 255, 255, 63, 0, 0, 0, 0, 0, 14, 0, 1, 131, 255, + 0, 254, 255, 255, 7, 0, 0, 0, 0, 0, 0, 20, 254, 33, 254, 0, + 12, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 16, 30, 32, 0, 0, + 12, 0, 0, 64, 6, 0, 0, 0, 134, 57, 2, 0, 0, 0, 35, 0, + 190, 33, 0, 0, 12, 0, 0, 252, 0, 0, 0, 144, 30, 32, 96, 0, + 12, 0, 0, 0, 4, 0, 0, 0, 1, 32, 0, 0, 17, 0, 0, 0, + 0, 0, 0, 208, 193, 61, 96, 0, 64, 48, 0, 0, 3, 0, 0, 0, + 0, 0, 0, 24, 0, 4, 92, 0, 0, 0, 242, 7, 192, 127, 0, 0, + 0, 0, 242, 31, 64, 127, 0, 0, 0, 0, 0, 3, 0, 0, 160, 2, + 0, 0, 254, 127, 223, 224, 255, 254, 255, 255, 255, 31, 64, 0, 0, 0, + 0, 224, 253, 102, 0, 0, 0, 195, 1, 0, 30, 0, 100, 32, 0, 32, + 0, 0, 0, 224, 0, 0, 28, 0, 0, 0, 12, 0, 0, 0, 176, 63, + 64, 254, 143, 32, 0, 248, 0, 0, 8, 0, 0, 0, 96, 0, 0, 0, + 0, 2, 0, 0, 135, 1, 4, 14, 0, 0, 128, 9, 0, 0, 64, 127, + 229, 31, 248, 159, 128, 0, 255, 255, 255, 127, 0, 0, 15, 0, 0, 0, + 0, 0, 208, 23, 0, 248, 15, 0, 60, 59, 0, 0, 64, 163, 3, 0, + 0, 240, 207, 0, 0, 0, 0, 63, 0, 0, 247, 255, 253, 33, 16, 3, + 0, 240, 255, 255, 255, 7, 0, 1, 0, 0, 0, 248, 0, 0, 0, 160, + 3, 224, 0, 224, 0, 224, 0, 96, 0, 248, 0, 3, 144, 124, 0, 0, + 223, 255, 2, 128, 0, 0, 255, 31, 255, 255, 1, 0, 0, 0, 0, 48, + 0, 128, 3, 0, 0, 128, 0, 128, 0, 128, 0, 0, 32, 0, 0, 0, + 0, 60, 62, 8, 0, 0, 0, 126, 0, 0, 0, 112, 0, 0, 32, 0, + 0, 16, 0, 0, 0, 128, 247, 191, 0, 0, 0, 240, 0, 0, 3, 0, + 0, 7, 0, 0, 0, 0, 28, 3, 68, 8, 0, 0, 96, 16, 0, 0, + 48, 0, 0, 0, 255, 255, 3, 128, 192, 63, 0, 0, 128, 255, 3, 0, + 0, 0, 200, 51, 0, 126, 102, 0, 8, 16, 0, 0, 0, 0, 1, 16, + 0, 0, 157, 193, 2, 0, 0, 32, 0, 48, 88, 0, 0, 14, 0, 0, + 32, 33, 0, 0, 0, 0, 252, 255, 255, 255, 8, 0, 255, 255, 0, 0, + 0, 0, 36, 0, 0, 0, 0, 128, 0, 0, 0, 192, 8, 0, 0, 14, + 0, 0, 0, 32, 0, 0, 192, 7, 191, 255, 255, 255, 255, 255, 253, 7, + 110, 240, 0, 0, 0, 0, 0, 135, 240, 0, 0, 0, 0, 64, 0, 0, + 0, 190, 0, 0, 0, 24, 0, 0, 60, 0, 0, 0, 0, 0, 0, 255, + 127, 0, 0, 0, 0, 0, 25, 128, 0, 0, 120, 38, 4, 32, 0, 0, + 128, 239, 31, 0, 0, 0, 8, 0, 0, 0, 192, 127, 0, 158, 0, 0, + 0, 128, 211, 64, 248, 7, 0, 0, 192, 31, 31, 0, 1, 64, 5, 0, + 92, 0, 0, 64, 0, 0, 248, 133, 13, 0, 0, 0, 0, 0, 60, 176, + 1, 0, 0, 48, 0, 0, 248, 167, 0, 40, 191, 0, 188, 15, 0, 0, + 0, 128, 255, 6, 0, 0, 0, 88, 0, 0, 240, 12, 254, 7, 0, 0, + 0, 0, 248, 121, 128, 0, 126, 14, 0, 252, 127, 3, 0, 0, 127, 191, + 255, 252, 109, 0, 0, 0, 126, 180, 191, 0, 0, 0, 0, 0, 163, 0, + 0, 0, 24, 0, 5, 0, 0, 4, 129, 255, 63, 0, 255, 227, 0, 0, + 0, 0, 31, 0, 0, 0, 127, 0, 0, 128, 255, 255, 27, 0, 0, 0, + 0, 0, 239, 111, 0, 0, 0, 96, 255, 63, 255, 255, 128, 3, 248, 255, + 231, 15, 0, 0, 0, 60, 0, 0, 28, 0, 0, 0, 255, 255, 127, 248, + 255, 31, 32, 0, 16, 0, 0, 248, 254, 255, 0, 0, 127, 255, 255, 249, + 219, 7, 255, 255, 0, 0, 255, 63, 0, 240, 0, 0, 0, 192, 0, 0, + 240, 15, 0, 0 +}; + +RE_UINT32 re_get_case_ignorable(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_case_ignorable_table_1[field_2]; + v = re_case_ignorable_table_2[(v << 5) | field_1]; + v = re_case_ignorable_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Changes_When_Casefolded. */ +static RE_UINT8 re_changes_when_casefolded_table_1[] = { + 0, 1, 2, 2, 3, 2, 2, 4, 5, 6, 2, 7, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 8, 9, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 10, 11, + 2, 12, 2, 13, 2, 2, 14, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 15, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 +}; + +static RE_UINT8 re_changes_when_casefolded_table_2[] = { + 0, 0, 1, 0, 0, 2, 3, 0, 4, 5, 6, 7, 8, 9, 10, 11, + 4, 12, 13, 0, 0, 0, 0, 0, 0, 0, 14, 15, 16, 17, 18, 19, + 20, 21, 0, 4, 22, 4, 23, 4, 4, 24, 25, 0, 26, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 20, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, + 0, 0, 0, 0, 29, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 31, 4, 4, 4, 32, 33, 34, 35, 20, 36, 37, 38, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 0, 21, 40, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 41, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 20, 21, 0, 42, 4, 4, 4, 43, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 44, 45, 0, 0, 0, 0, 46, 4, 47, 48, 49, 50, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 20, 20, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 20, 53, 0, 0, 0, 51, 54, 0, 0, 0, 0, 55, 56, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 20, 57, 0, 0, 0, 0, 51, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 20, 59, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_changes_when_casefolded_table_3[] = { + 0, 0, 0, 0, 254, 255, 255, 7, 0, 0, 32, 0, 255, 255, 127, 255, + 85, 85, 85, 85, 85, 85, 85, 170, 170, 86, 85, 85, 85, 85, 85, 171, + 214, 206, 219, 177, 213, 210, 174, 17, 176, 173, 170, 74, 85, 85, 214, 85, + 85, 85, 5, 108, 122, 85, 0, 0, 32, 0, 0, 0, 0, 0, 69, 128, + 64, 215, 254, 255, 251, 15, 0, 0, 4, 128, 99, 85, 85, 85, 179, 230, + 255, 255, 255, 255, 255, 255, 0, 0, 1, 84, 85, 85, 171, 42, 85, 85, + 85, 85, 254, 255, 255, 255, 127, 0, 128, 0, 0, 0, 191, 32, 0, 0, + 0, 0, 0, 63, 255, 3, 255, 255, 255, 255, 255, 231, 85, 85, 21, 76, + 0, 255, 0, 63, 0, 255, 0, 255, 0, 63, 0, 170, 0, 255, 0, 0, + 255, 255, 156, 31, 156, 31, 0, 15, 0, 31, 156, 31, 64, 12, 4, 0, + 8, 0, 0, 0, 0, 0, 192, 255, 157, 234, 37, 192, 5, 40, 4, 0, + 85, 21, 0, 0, 85, 85, 85, 5, 84, 85, 84, 85, 85, 85, 0, 106, + 85, 40, 69, 85, 85, 125, 95, 85, 245, 26, 65, 21, 0, 0, 255, 255, + 127, 0, 248, 0, 255, 0, 0, 0, 255, 255, 15, 0, 0, 0, 255, 247, + 255, 247, 55, 0, 255, 255, 7, 0, 63, 0, 0, 0, 3, 0, 0, 0 +}; + +RE_UINT32 re_get_changes_when_casefolded(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_changes_when_casefolded_table_1[field_2]; + v = re_changes_when_casefolded_table_2[(v << 5) | field_1]; + v = re_changes_when_casefolded_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Changes_When_Casemapped. */ +static RE_UINT8 re_changes_when_casemapped_table_1[] = { + 0, 1, 2, 2, 3, 2, 2, 4, 5, 6, 2, 7, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 8, 9, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 10, 11, + 2, 12, 2, 13, 2, 2, 14, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 15, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 +}; + +static RE_UINT8 re_changes_when_casemapped_table_2[] = { + 0, 0, 1, 1, 0, 2, 3, 3, 4, 5, 4, 4, 6, 7, 8, 4, + 4, 9, 10, 11, 12, 0, 0, 0, 0, 0, 13, 14, 15, 16, 17, 18, + 4, 4, 4, 4, 19, 4, 4, 4, 4, 20, 21, 22, 23, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 4, 24, 25, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 26, + 0, 0, 0, 0, 27, 25, 0, 0, 0, 0, 0, 28, 29, 0, 0, 0, + 4, 4, 4, 4, 30, 4, 4, 4, 26, 4, 31, 32, 4, 33, 34, 35, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 29, 4, 37, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 38, 4, 39, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 40, 4, 4, 4, 41, 4, 42, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 43, 44, 0, 0, 0, 0, 45, 4, 46, 47, 48, 49, 50, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 52, 4, 4, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 53, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, + 4, 4, 54, 0, 0, 52, 55, 44, 0, 0, 0, 56, 57, 58, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 59, 4, 59, 0, 0, 52, 60, 61, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 62, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_changes_when_casemapped_table_3[] = { + 0, 0, 0, 0, 254, 255, 255, 7, 0, 0, 32, 0, 255, 255, 127, 255, + 255, 255, 255, 255, 255, 255, 255, 254, 255, 223, 255, 255, 255, 243, 255, 179, + 240, 255, 255, 255, 253, 255, 15, 252, 255, 255, 223, 26, 123, 159, 38, 32, + 141, 31, 4, 96, 32, 0, 0, 0, 0, 0, 207, 184, 64, 215, 255, 255, + 251, 255, 255, 255, 255, 255, 227, 255, 255, 255, 191, 239, 3, 252, 255, 255, + 255, 255, 254, 255, 255, 255, 127, 0, 254, 255, 255, 255, 255, 0, 0, 0, + 191, 32, 255, 255, 255, 255, 255, 231, 255, 255, 63, 63, 255, 7, 255, 255, + 0, 0, 0, 34, 0, 64, 0, 0, 255, 255, 255, 79, 63, 63, 255, 170, + 255, 255, 255, 63, 255, 255, 223, 95, 220, 31, 207, 15, 255, 31, 220, 31, + 64, 12, 4, 0, 24, 0, 0, 0, 0, 0, 192, 255, 255, 3, 0, 0, + 255, 255, 109, 192, 15, 120, 12, 0, 191, 32, 0, 0, 255, 63, 0, 0, + 255, 255, 255, 15, 252, 255, 252, 255, 255, 255, 0, 254, 255, 56, 223, 255, + 255, 127, 255, 255, 255, 63, 195, 31, 0, 0, 96, 0, 0, 0, 8, 0, + 0, 0, 255, 255, 127, 0, 248, 0, 255, 255, 0, 0, 255, 255, 15, 255, + 0, 0, 255, 247, 255, 247, 183, 255, 251, 255, 251, 27, 255, 255, 7, 0, + 63, 0, 255, 255, 63, 0, 0, 0, 15, 0, 0, 0 +}; + +RE_UINT32 re_get_changes_when_casemapped(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_changes_when_casemapped_table_1[field_2]; + v = re_changes_when_casemapped_table_2[(v << 5) | field_1]; + v = re_changes_when_casemapped_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Changes_When_Lowercased. */ +static RE_UINT8 re_changes_when_lowercased_table_1[] = { + 0, 1, 2, 2, 3, 2, 2, 4, 5, 6, 2, 7, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 8, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, + 2, 10, 2, 11, 2, 2, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 13, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 14, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 +}; + +static RE_UINT8 re_changes_when_lowercased_table_2[] = { + 0, 0, 1, 0, 0, 0, 2, 0, 3, 4, 5, 6, 7, 8, 9, 10, + 3, 11, 12, 0, 0, 0, 0, 0, 0, 0, 0, 13, 14, 15, 16, 17, + 18, 19, 0, 3, 20, 3, 21, 3, 3, 22, 23, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 18, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 25, + 0, 0, 0, 0, 26, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 3, 3, 3, 28, 3, 3, 3, 29, 30, 31, 32, 30, 33, 34, 35, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 19, 37, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 38, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 18, 19, 0, 39, 3, 3, 3, 40, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 41, 42, 0, 0, 0, 0, 43, 3, 44, 45, 46, 47, 48, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 18, 49, 0, 0, 0, 50, 51, 0, 0, 0, 0, 52, 53, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 18, 54, 0, 0, 0, 0, 50, 55, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 18, 56, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_changes_when_lowercased_table_3[] = { + 0, 0, 0, 0, 254, 255, 255, 7, 255, 255, 127, 127, 85, 85, 85, 85, + 85, 85, 85, 170, 170, 84, 85, 85, 85, 85, 85, 43, 214, 206, 219, 177, + 213, 210, 174, 17, 176, 173, 170, 74, 85, 85, 214, 85, 85, 85, 5, 108, + 122, 85, 0, 0, 0, 0, 69, 128, 64, 215, 254, 255, 251, 15, 0, 0, + 0, 128, 0, 85, 85, 85, 144, 230, 255, 255, 255, 255, 255, 255, 0, 0, + 1, 84, 85, 85, 171, 42, 85, 85, 85, 85, 254, 255, 255, 255, 127, 0, + 191, 32, 0, 0, 255, 255, 63, 0, 0, 2, 255, 255, 255, 255, 255, 231, + 85, 85, 21, 64, 0, 255, 0, 63, 0, 255, 0, 255, 0, 63, 0, 170, + 0, 255, 0, 0, 0, 255, 0, 31, 0, 31, 0, 15, 0, 31, 0, 31, + 64, 12, 4, 0, 8, 0, 0, 0, 0, 0, 192, 255, 157, 234, 37, 192, + 5, 40, 4, 0, 85, 21, 0, 0, 85, 85, 85, 5, 84, 85, 84, 85, + 85, 85, 0, 106, 85, 40, 69, 85, 85, 125, 95, 85, 245, 26, 65, 21, + 0, 0, 32, 0, 255, 0, 0, 0, 0, 0, 255, 255, 255, 255, 15, 0, + 0, 0, 255, 247, 255, 247, 55, 0, 255, 255, 7, 0, 63, 0, 0, 0, + 3, 0, 0, 0 +}; + +RE_UINT32 re_get_changes_when_lowercased(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_changes_when_lowercased_table_1[field_2]; + v = re_changes_when_lowercased_table_2[(v << 5) | field_1]; + v = re_changes_when_lowercased_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Changes_When_Titlecased. */ +static RE_UINT8 re_changes_when_titlecased_table_1[] = { + 0, 1, 2, 2, 3, 2, 2, 4, 5, 6, 2, 7, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 8, 9, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 10, 11, + 2, 12, 2, 13, 2, 2, 14, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 15, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 +}; + +static RE_UINT8 re_changes_when_titlecased_table_2[] = { + 0, 0, 0, 1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 5, 13, 14, 15, 16, 0, 0, 0, 0, 0, 17, 18, 19, 20, 21, 22, + 0, 23, 24, 5, 25, 5, 26, 5, 5, 27, 0, 28, 29, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, + 0, 0, 0, 0, 31, 0, 0, 0, 0, 0, 0, 32, 33, 0, 0, 0, + 5, 5, 5, 5, 34, 5, 5, 5, 35, 36, 37, 38, 36, 39, 40, 41, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 23, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 23, 43, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 23, 24, 44, 5, 5, 5, 45, 24, 46, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 47, 48, 0, 0, 0, 0, 49, 5, 50, 51, 52, 53, 54, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 23, 24, 24, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 57, 58, 0, 0, 0, 59, 60, 0, 0, 0, 0, 61, 62, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 24, 63, 0, 0, 0, 23, 64, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 66, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_changes_when_titlecased_table_3[] = { + 0, 0, 0, 0, 254, 255, 255, 7, 0, 0, 32, 0, 0, 0, 0, 128, + 255, 255, 127, 255, 170, 170, 170, 170, 170, 170, 170, 84, 85, 171, 170, 170, + 170, 170, 170, 212, 41, 17, 36, 78, 42, 33, 81, 162, 208, 86, 85, 181, + 170, 170, 43, 170, 168, 170, 10, 144, 133, 170, 223, 26, 123, 159, 38, 32, + 141, 31, 4, 96, 32, 0, 0, 0, 0, 0, 138, 56, 0, 0, 1, 0, + 0, 240, 255, 255, 255, 127, 227, 170, 170, 170, 47, 9, 0, 0, 255, 255, + 255, 255, 255, 255, 2, 168, 170, 170, 84, 213, 170, 170, 170, 170, 0, 0, + 254, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 63, 255, 5, 0, 0, + 0, 0, 0, 34, 0, 64, 0, 0, 170, 170, 234, 15, 255, 0, 63, 0, + 255, 0, 255, 0, 63, 0, 255, 0, 255, 0, 255, 63, 255, 0, 223, 64, + 220, 0, 207, 0, 255, 0, 220, 0, 16, 0, 0, 0, 255, 3, 0, 0, + 98, 21, 72, 0, 10, 80, 8, 0, 191, 32, 0, 0, 170, 42, 0, 0, + 170, 170, 170, 10, 168, 170, 168, 170, 170, 170, 0, 148, 170, 16, 154, 170, + 170, 2, 160, 170, 10, 37, 130, 10, 0, 0, 64, 0, 0, 0, 8, 0, + 127, 0, 248, 0, 0, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 255, + 255, 255, 255, 15, 0, 0, 128, 255, 251, 255, 251, 27, 255, 255, 7, 0, + 63, 0, 0, 0, 252, 255, 255, 255, 15, 0, 0, 0 +}; + +RE_UINT32 re_get_changes_when_titlecased(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_changes_when_titlecased_table_1[field_2]; + v = re_changes_when_titlecased_table_2[(v << 5) | field_1]; + v = re_changes_when_titlecased_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Changes_When_Uppercased. */ +static RE_UINT8 re_changes_when_uppercased_table_1[] = { + 0, 1, 2, 2, 3, 2, 2, 4, 5, 6, 2, 7, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 8, 9, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 10, 11, + 2, 12, 2, 13, 2, 2, 14, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 15, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 +}; + +static RE_UINT8 re_changes_when_uppercased_table_2[] = { + 0, 0, 0, 1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 5, 13, 14, 15, 16, 0, 0, 0, 0, 0, 17, 18, 19, 20, 21, 22, + 0, 23, 24, 5, 25, 5, 26, 5, 5, 27, 0, 28, 29, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 23, 30, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, + 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 33, 34, 0, 0, 0, + 5, 5, 5, 5, 35, 5, 5, 5, 36, 37, 38, 39, 24, 40, 41, 42, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 23, 43, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 23, 44, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 23, 24, 45, 5, 5, 5, 46, 24, 47, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 48, 49, 0, 0, 0, 0, 50, 5, 51, 52, 53, 54, 55, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 23, 24, 24, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 58, 59, 0, 0, 0, 60, 61, 0, 0, 0, 0, 62, 63, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 24, 64, 0, 0, 0, 23, 65, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 67, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_changes_when_uppercased_table_3[] = { + 0, 0, 0, 0, 254, 255, 255, 7, 0, 0, 32, 0, 0, 0, 0, 128, + 255, 255, 127, 255, 170, 170, 170, 170, 170, 170, 170, 84, 85, 171, 170, 170, + 170, 170, 170, 212, 41, 17, 36, 78, 42, 33, 81, 162, 96, 91, 85, 181, + 170, 170, 45, 170, 168, 170, 10, 144, 133, 170, 223, 26, 123, 159, 38, 32, + 141, 31, 4, 96, 32, 0, 0, 0, 0, 0, 138, 56, 0, 0, 1, 0, + 0, 240, 255, 255, 255, 127, 227, 170, 170, 170, 47, 9, 0, 0, 255, 255, + 255, 255, 255, 255, 2, 168, 170, 170, 84, 213, 170, 170, 170, 170, 0, 0, + 254, 255, 255, 255, 255, 0, 0, 0, 255, 255, 255, 231, 0, 0, 0, 63, + 255, 5, 0, 0, 0, 0, 0, 34, 0, 64, 0, 0, 170, 170, 234, 15, + 255, 0, 63, 0, 255, 0, 255, 0, 63, 0, 255, 0, 255, 0, 255, 63, + 255, 255, 223, 80, 220, 16, 207, 0, 255, 0, 220, 16, 16, 0, 0, 0, + 255, 3, 0, 0, 98, 21, 72, 0, 10, 80, 8, 0, 191, 32, 0, 0, + 170, 42, 0, 0, 170, 170, 170, 10, 168, 170, 168, 170, 170, 170, 0, 148, + 170, 16, 154, 170, 170, 2, 160, 170, 10, 37, 130, 10, 0, 0, 64, 0, + 0, 0, 8, 0, 127, 0, 248, 0, 0, 255, 255, 255, 255, 255, 0, 0, + 0, 0, 0, 255, 255, 255, 255, 15, 0, 0, 128, 255, 251, 255, 251, 27, + 255, 255, 7, 0, 63, 0, 0, 0, 252, 255, 255, 255, 15, 0, 0, 0 +}; + +RE_UINT32 re_get_changes_when_uppercased(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_changes_when_uppercased_table_1[field_2]; + v = re_changes_when_uppercased_table_2[(v << 5) | field_1]; + v = re_changes_when_uppercased_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Dash. */ +static RE_UINT8 re_dash_table_1[] = { + 0, 1, 2, 2, 2, 3, 4, 2, 5, 2, 2, 6, 7, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 8, + 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 +}; + +static RE_UINT8 re_dash_table_2[] = { + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 0, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 12, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 15, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 16, 17, 18, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_dash_table_3[] = { + 0, 0, 0, 0, 0, 32, 0, 0, 0, 4, 0, 0, 0, 0, 0, 64, + 1, 0, 0, 0, 64, 0, 0, 0, 0, 0, 63, 0, 0, 0, 8, 0, + 0, 0, 0, 8, 0, 8, 0, 0, 0, 0, 4, 0, 0, 0, 128, 4, + 0, 0, 0, 12, 1, 0, 0, 32, 0, 0, 0, 16, 0, 0, 1, 0, + 0, 0, 6, 0, 0, 0, 0, 1, 8, 0, 0, 0, 0, 64, 0, 0 +}; + +RE_UINT32 re_get_dash(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_dash_table_1[field_2]; + v = re_dash_table_2[(v << 5) | field_1]; + v = re_dash_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Decomposition_Type. */ +static RE_UINT8 re_decomposition_type_table_1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 13, 14, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 16, 5, 5, 5, 5, 5, 5, 5, 5, 17, 18, + 5, 19, 5, 5, 20, 21, 22, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 23, 5, 5, 24, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 25, 26, 27, 5, 5, 28, 5, 5, 29, 30, 5, 31, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 32, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 +}; + +static RE_UINT8 re_decomposition_type_table_2[] = { + 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 0, 8, 9, 10, + 11, 12, 0, 0, 0, 13, 14, 15, 0, 0, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 0, 0, 26, 27, 0, 0, 0, 0, 28, 0, 0, 0, + 0, 29, 0, 30, 0, 0, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 33, 0, 0, 0, 34, 0, + 0, 35, 36, 0, 0, 0, 0, 0, 0, 0, 37, 0, 38, 0, 39, 0, + 0, 0, 40, 0, 0, 0, 41, 0, 0, 0, 39, 0, 0, 0, 42, 0, + 0, 43, 0, 0, 0, 43, 44, 0, 45, 0, 46, 47, 48, 49, 0, 0, + 0, 50, 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 52, 53, 54, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 56, 57, 58, 59, 0, 0, + 60, 60, 60, 60, 61, 60, 60, 62, 63, 60, 64, 65, 60, 66, 67, 68, + 69, 70, 71, 72, 73, 74, 0, 0, 75, 76, 77, 78, 79, 80, 81, 0, + 82, 83, 84, 85, 86, 87, 0, 88, 0, 89, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 90, 78, 91, 92, 93, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 94, 0, 0, 95, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 97, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, + 0, 0, 0, 0, 99, 0, 0, 43, 78, 78, 78, 78, 78, 78, 100, 0, + 101, 102, 103, 104, 105, 103, 104, 106, 0, 107, 78, 78, 108, 0, 0, 0, + 109, 78, 110, 111, 92, 92, 112, 113, 114, 114, 115, 116, 114, 114, 114, 117, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 119, 0, 0, 0, 120, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 122, 0, 0, 0, 0, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 123, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 60, 60, 60, 60, 60, 60, 60, 60, + 124, 125, 60, 126, 60, 60, 62, 0, 127, 128, 129, 130, 131, 132, 133, 134, + 135, 135, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, + 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 158, 159, 160, 161, 162, 163, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 164, 165, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166, 167, 0, 0, + 0, 0, 0, 0, 168, 169, 0, 0, 0, 170, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171, 0, 172, 0, 173, 0, + 0, 0, 0, 0, 0, 174, 0, 0, 0, 0, 0, 0, 0, 175, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 177, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 179, 180, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181, 182, 0, 183, 184, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 185, 185, 186, 185, 187, 188, 189, 185, 190, 191, 192, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 185, 193, 185, 185, 185, 185, 185, 185, 185, 185, 194, 185, + 0, 195, 196, 197, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 189, 198, 199, 200, 201, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 203, 204, 205, 206, 207, 0, 0, 0, + 208, 209, 210, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_decomposition_type_table_3[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 3, 0, 0, 0, 0, 2, + 0, 0, 3, 3, 2, 2, 0, 0, 2, 3, 3, 0, 4, 4, 4, 0, + 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 0, 5, 5, 5, 5, 5, 5, 0, 0, 5, 5, 5, 5, 5, 0, 0, + 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 0, 5, 5, 5, 5, 5, 5, 0, 0, 5, 5, 5, 5, 5, 0, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 0, 2, 2, 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, 2, + 2, 0, 0, 5, 5, 5, 5, 5, 5, 2, 0, 0, 5, 5, 5, 5, + 5, 5, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, + 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, + 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, + 5, 5, 5, 5, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 2, 2, 2, 5, 5, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 5, 5, + 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, + 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 0, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 2, 0, 0, 0, 5, 0, + 0, 0, 0, 0, 2, 5, 5, 5, 5, 5, 5, 0, 5, 0, 5, 5, + 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, + 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 0, + 2, 2, 2, 5, 5, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 0, 2, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, + 5, 5, 0, 5, 0, 0, 0, 5, 0, 0, 0, 0, 5, 5, 5, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 0, 5, 0, 0, 0, 5, 0, 0, 0, 0, 5, 5, 5, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 0, 0, 5, 5, 0, 0, 5, 5, 5, 5, 5, 5, + 0, 0, 5, 5, 5, 5, 5, 5, 0, 0, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, + 5, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, + 0, 5, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 5, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 0, 0, 5, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 5, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 0, 0, 0, 5, 5, 0, 5, 5, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 5, 5, 5, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, + 0, 0, 5, 0, 0, 0, 0, 5, 0, 0, 0, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 0, 5, 5, 2, 5, 2, 0, 0, 0, 0, 0, 0, + 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, + 0, 0, 5, 0, 0, 0, 0, 5, 0, 0, 0, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, + 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 5, 0, 0, + 5, 5, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 0, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 5, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 0, 0, 5, 5, 5, 5, 5, 5, 0, 0, + 5, 5, 5, 5, 5, 5, 0, 0, 5, 5, 5, 5, 5, 5, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 0, 5, 0, 5, 0, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 2, 5, 2, + 2, 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 0, 0, 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 0, 0, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, 2, 0, + 5, 5, 2, 2, 2, 2, 2, 1, 2, 2, 2, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 2, 2, 0, 2, 2, 0, 0, 0, 0, 2, 0, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 3, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 0, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 7, 2, 0, 2, 2, 2, 0, 2, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 0, 7, 2, 0, 0, 7, 7, 7, 7, 7, 0, 0, + 3, 2, 3, 0, 7, 0, 5, 0, 7, 0, 5, 5, 7, 7, 0, 7, + 7, 7, 0, 7, 7, 2, 2, 2, 2, 7, 0, 2, 7, 7, 7, 7, + 7, 0, 0, 0, 0, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 0, 0, 0, 0, 5, 0, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 0, 5, 0, 0, 0, 0, 0, 2, 2, 0, 2, + 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5, 0, 0, 5, 0, 0, 5, 0, 5, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, + 5, 5, 0, 0, 5, 5, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, + 5, 5, 0, 0, 5, 5, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2, 0, 2, 2, 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 5, 0, + 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, + 5, 0, 5, 0, 0, 5, 0, 5, 0, 5, 0, 0, 0, 0, 0, 0, + 5, 5, 0, 5, 5, 0, 5, 5, 0, 5, 5, 0, 5, 5, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 2, 2, 0, 5, 10, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 0, 0, 5, 5, 5, 5, 0, 0, 0, 5, 10, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, + 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, + 2, 2, 2, 2, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 11, 11, 11, 11, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 11, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 3, 3, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, + 5, 0, 5, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, + 5, 0, 5, 0, 0, 5, 5, 0, 0, 0, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 5, 0, 5, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, 0, 5, 0, + 5, 5, 0, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, + 12, 13, 12, 13, 14, 15, 12, 13, 14, 15, 12, 13, 14, 15, 12, 13, + 14, 15, 12, 13, 14, 15, 12, 13, 14, 15, 12, 13, 14, 15, 12, 13, + 14, 15, 12, 13, 14, 15, 12, 13, 14, 15, 12, 13, 14, 15, 12, 13, + 14, 15, 12, 13, 12, 13, 12, 13, 12, 13, 12, 13, 12, 13, 12, 13, + 14, 15, 12, 13, 14, 15, 12, 13, 14, 15, 12, 13, 14, 15, 12, 13, + 12, 13, 14, 15, 12, 13, 12, 13, 14, 15, 12, 13, 14, 15, 12, 13, + 12, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 12, 13, 14, 15, 12, 13, 12, 13, 12, 13, 12, 12, 13, + 12, 13, 12, 13, 12, 13, 14, 15, 14, 15, 12, 13, 12, 13, 12, 13, + 12, 13, 12, 13, 12, 13, 12, 13, 14, 12, 13, 14, 12, 13, 14, 15, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, + 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 13, 12, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 13, 14, 14, 14, 14, 14, 14, 13, 14, 13, 13, 14, 14, 13, 13, + 14, 14, 13, 14, 13, 14, 13, 13, 14, 13, 13, 14, 13, 14, 13, 13, + 14, 13, 14, 14, 13, 13, 13, 14, 13, 13, 13, 13, 13, 14, 13, 13, + 13, 13, 13, 14, 13, 13, 14, 13, 14, 14, 14, 13, 14, 14, 14, 14, + 0, 0, 14, 14, 14, 14, 13, 13, 14, 13, 13, 13, 13, 14, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 14, 14, 13, 13, 14, 13, 14, 13, 13, 13, 13, 13, + 13, 13, 13, 14, 14, 14, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 0, 0, 10, 10, 2, 2, 2, 2, 2, 2, 2, + 16, 16, 16, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 0, 16, 16, 16, 16, 0, 0, 0, 0, + 12, 15, 12, 0, 12, 0, 12, 15, 12, 15, 12, 15, 12, 15, 12, 15, + 12, 12, 13, 12, 13, 12, 13, 12, 13, 12, 13, 14, 15, 12, 13, 12, + 13, 14, 15, 12, 13, 12, 13, 14, 15, 12, 13, 14, 15, 12, 13, 14, + 15, 12, 13, 14, 15, 12, 13, 14, 15, 12, 13, 12, 13, 12, 13, 12, + 13, 12, 13, 14, 15, 12, 13, 14, 15, 12, 13, 14, 15, 12, 13, 14, + 15, 12, 13, 14, 15, 12, 13, 14, 15, 12, 13, 14, 15, 12, 13, 14, + 15, 12, 13, 14, 15, 12, 13, 14, 15, 12, 13, 14, 15, 12, 13, 14, + 15, 12, 13, 14, 15, 12, 13, 14, 15, 12, 13, 14, 15, 12, 13, 12, + 13, 12, 13, 14, 15, 12, 13, 12, 13, 12, 13, 12, 13, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, + 0, 0, 17, 17, 17, 17, 17, 17, 0, 0, 17, 17, 17, 17, 17, 17, + 0, 0, 17, 17, 17, 17, 17, 17, 0, 0, 17, 17, 17, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 0, 17, 17, 17, 17, 17, 17, 17, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, + 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 5, 0, 5, 5, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 5, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, + 0, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, + 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, + 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 7, 7, + 0, 0, 7, 0, 0, 7, 7, 0, 0, 7, 7, 7, 7, 0, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 7, 0, 7, 7, 7, + 7, 7, 7, 7, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 0, 7, 7, 7, 7, 0, 0, 7, 7, 7, + 7, 7, 7, 7, 7, 0, 7, 7, 7, 7, 7, 7, 7, 0, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 7, 7, 7, 7, 0, + 7, 7, 7, 7, 7, 0, 7, 0, 0, 0, 7, 7, 7, 7, 7, 7, + 7, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 0, 0, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7, 7, 0, 7, 0, 0, 7, 0, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 0, 7, 7, 7, 7, 0, 7, 0, 7, 0, 0, 0, 0, + 0, 0, 7, 0, 0, 0, 0, 7, 0, 7, 0, 7, 0, 7, 7, 7, + 0, 7, 7, 0, 7, 0, 0, 7, 0, 7, 0, 7, 0, 7, 0, 7, + 0, 7, 7, 0, 7, 0, 0, 7, 7, 7, 7, 0, 7, 7, 7, 7, + 7, 7, 7, 0, 7, 7, 7, 7, 0, 7, 7, 7, 7, 0, 7, 0, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, + 0, 7, 7, 7, 0, 7, 7, 7, 7, 7, 0, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 8, 8, 8, 8, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, + 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, 0 +}; + +RE_UINT32 re_get_decomposition_type(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = codepoint & 0x1F; + + v = re_decomposition_type_table_1[field_2]; + v = re_decomposition_type_table_2[(v << 5) | field_1]; + v = re_decomposition_type_table_3[(v << 5) | field_0]; + + return v; +} + +/* Default_Ignorable_Code_Point. */ +static RE_UINT8 re_default_ignorable_code_point_table_1[] = { + 0, 1, 2, 2, 3, 4, 5, 2, 6, 2, 2, 2, 7, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 8, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, + 2, 2, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 11, 11, 11, 11, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 +}; + +static RE_UINT8 re_default_ignorable_code_point_table_2[] = { + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, + 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 7, 8, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 5, 0, 11, + 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14 +}; + +static RE_UINT8 re_default_ignorable_code_point_table_3[] = { + 0, 0, 0, 0, 0, 32, 0, 0, 0, 128, 0, 0, 0, 0, 0, 16, + 0, 0, 0, 128, 1, 0, 0, 0, 0, 0, 48, 0, 0, 248, 0, 0, + 0, 124, 0, 0, 255, 255, 0, 0, 16, 0, 0, 0, 0, 0, 255, 1, + 15, 0, 0, 0, 0, 0, 248, 7, 255, 255, 255, 255 +}; + +RE_UINT32 re_get_default_ignorable_code_point(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_default_ignorable_code_point_table_1[field_2]; + v = re_default_ignorable_code_point_table_2[(v << 5) | field_1]; + v = re_default_ignorable_code_point_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Deprecated. */ +RE_UINT32 re_get_deprecated(RE_UINT32 codepoint) { + if (codepoint == 0x0149) + return 1; + if (codepoint == 0x0673) + return 1; + if (codepoint == 0x0F77) + return 1; + if (codepoint == 0x0F79) + return 1; + if (0x17A3 <= codepoint && codepoint <= 0x17A4) + return 1; + if (0x206A <= codepoint && codepoint <= 0x206F) + return 1; + if (0x2329 <= codepoint && codepoint <= 0x232A) + return 1; + if (codepoint == 0x0E0001) + return 1; + + return 0; +} + +/* Diacritic. */ +static RE_UINT8 re_diacritic_table_1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 8, 9, 10, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 11, 12, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 8, 8, 8, 8, 8, 23, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 24, 8, 25, 26, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 27, 8, 8, 8, 8, + 8, 8, 8, 28, 29, 8, 8, 8, 30, 31, 32, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 +}; + +static RE_UINT8 re_diacritic_table_2[] = { + 0, 0, 1, 2, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 4, 5, 5, 5, 5, 6, 7, 8, 0, 0, 0, + 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 10, 0, 11, 12, 13, 0, + 0, 0, 14, 0, 0, 0, 15, 16, 0, 4, 17, 0, 0, 18, 0, 19, + 20, 0, 0, 0, 21, 0, 22, 23, 0, 24, 25, 26, 0, 24, 27, 0, + 0, 24, 27, 0, 0, 24, 27, 28, 0, 24, 29, 0, 0, 0, 27, 0, + 0, 24, 27, 0, 0, 24, 27, 0, 0, 30, 27, 0, 0, 0, 31, 0, + 0, 32, 33, 0, 0, 32, 34, 0, 20, 35, 0, 0, 36, 0, 37, 0, + 0, 38, 0, 39, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 41, 42, 0, 0, 0, 0, 43, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 45, 0, 46, 47, 0, 0, 42, 48, 49, 0, 50, 0, 51, + 0, 52, 0, 53, 0, 0, 4, 54, 0, 55, 5, 17, 0, 0, 56, 57, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, 59, 60, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 61, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 63, 0, 0, 64, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 65, 66, 0, 0, 67, 5, 68, 0, 0, 69, 0, 0, 20, + 37, 70, 0, 0, 0, 0, 48, 71, 0, 72, 73, 0, 0, 73, 2, 74, + 0, 0, 0, 75, 0, 15, 76, 77, 0, 0, 78, 79, 0, 0, 0, 80, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 81, 0, 0, 0, 0, 0, 0, 0, 1, 2, 82, 83, 0, 0, 84, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 86, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 87, 0, 0, 0, 0, 0, 88, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 90, 91, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 18, 0, 92, 0, 0, 0, + 0, 0, 37, 82, 0, 93, 0, 0, 0, 94, 0, 73, 0, 0, 95, 0, + 0, 96, 0, 0, 0, 0, 0, 97, 0, 30, 27, 98, 0, 0, 99, 100, + 0, 0, 101, 0, 0, 0, 102, 0, 0, 0, 0, 0, 0, 15, 2, 0, + 0, 15, 0, 0, 0, 52, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, + 0, 93, 0, 0, 0, 0, 0, 0, 0, 104, 84, 0, 0, 0, 0, 2, + 0, 42, 105, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 106, 0, 107, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 0, 0, 0, 0, 0, + 0, 0, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 110, 0, 111, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113, 0, 0, 67, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 5, 115, 116, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 118, 119, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 4, 5, 120, 0, 0, 0, 0, 0, 111, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 90, 0, 121, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 111, 0, 0, 0, 123, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_diacritic_table_3[] = { + 0, 0, 0, 0, 0, 0, 0, 64, 1, 0, 0, 0, 0, 129, 144, 1, + 0, 0, 255, 255, 255, 255, 255, 255, 255, 127, 255, 224, 7, 0, 48, 4, + 48, 0, 0, 0, 248, 0, 0, 0, 0, 0, 0, 2, 0, 0, 254, 255, + 251, 255, 255, 191, 22, 0, 0, 0, 0, 248, 135, 1, 0, 0, 0, 128, + 97, 28, 0, 0, 255, 7, 0, 0, 192, 255, 1, 0, 0, 248, 63, 0, + 0, 0, 0, 3, 0, 0, 0, 255, 0, 254, 7, 0, 248, 255, 255, 127, + 0, 0, 0, 16, 0, 32, 30, 0, 0, 0, 2, 0, 0, 32, 0, 0, + 0, 0, 0, 224, 0, 32, 32, 0, 0, 0, 0, 24, 0, 4, 0, 0, + 0, 0, 0, 4, 128, 95, 0, 0, 0, 31, 0, 0, 0, 0, 160, 194, + 220, 0, 0, 0, 64, 0, 0, 0, 0, 0, 128, 6, 24, 62, 0, 0, + 128, 191, 0, 12, 0, 0, 48, 0, 0, 0, 16, 0, 0, 254, 15, 32, + 0, 0, 0, 14, 1, 0, 224, 159, 0, 0, 255, 127, 254, 15, 0, 0, + 16, 0, 0, 0, 0, 248, 15, 0, 0, 12, 0, 0, 64, 0, 12, 0, + 0, 0, 192, 0, 0, 0, 0, 63, 255, 33, 144, 3, 0, 240, 255, 255, + 240, 255, 0, 0, 0, 0, 224, 255, 0, 0, 0, 160, 3, 224, 0, 224, + 0, 224, 0, 96, 0, 128, 3, 0, 0, 128, 0, 0, 0, 252, 0, 0, + 0, 0, 0, 30, 0, 128, 0, 176, 0, 0, 0, 48, 0, 0, 3, 0, + 3, 0, 0, 0, 0, 7, 0, 0, 0, 16, 0, 0, 255, 255, 3, 0, + 0, 120, 0, 0, 0, 0, 8, 0, 32, 0, 0, 0, 0, 0, 0, 56, + 7, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 248, 0, 14, 0, 0, + 0, 48, 0, 0, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 0, 192, + 8, 0, 0, 0, 191, 255, 255, 255, 255, 255, 253, 7, 0, 0, 0, 135, + 96, 0, 0, 0, 252, 0, 0, 0, 0, 64, 0, 0, 0, 62, 0, 0, + 60, 0, 0, 0, 0, 0, 0, 6, 0, 0, 24, 0, 1, 28, 0, 0, + 0, 0, 96, 0, 0, 6, 0, 0, 192, 31, 31, 0, 0, 192, 13, 0, + 6, 0, 0, 0, 68, 0, 0, 0, 12, 0, 0, 0, 0, 8, 0, 0, + 0, 0, 0, 96, 128, 0, 0, 0, 52, 0, 0, 0, 0, 0, 128, 0, + 6, 0, 0, 4, 128, 255, 63, 0, 0, 0, 31, 0, 0, 0, 127, 0, + 0, 24, 0, 0, 0, 128, 255, 255, 0, 0, 239, 111, 255, 63, 255, 255, + 127, 0, 0, 0, 128, 227, 7, 248, 231, 15, 0, 0, 0, 60, 0, 0, + 255, 63, 0, 0, 0, 240, 0, 0, 0, 192, 0, 0, 112, 7, 0, 0 +}; + +RE_UINT32 re_get_diacritic(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_diacritic_table_1[field_2]; + v = re_diacritic_table_2[(v << 5) | field_1]; + v = re_diacritic_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* East_Asian_Width. */ +static RE_UINT8 re_east_asian_width_table_1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 15, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 16, 13, 13, 17, 17, 17, 17, 17, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 13, 30, 31, 32, 31, 31, + 33, 34, 13, 13, 13, 13, 13, 13, 35, 13, 36, 37, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 38, + 13, 13, 13, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 51, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 52, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 52 +}; + +static RE_UINT16 re_east_asian_width_table_2[] = { + 0, 1, 1, 2, 0, 3, 4, 5, 6, 7, 8, 9, 0, 0, 10, 0, + 0, 0, 11, 12, 0, 0, 13, 0, 14, 14, 14, 15, 16, 17, 18, 0, + 19, 14, 20, 0, 0, 0, 0, 0, 0, 21, 22, 0, 23, 0, 24, 25, + 0, 0, 0, 0, 0, 0, 0, 0, 26, 0, 27, 0, 0, 28, 0, 29, + 0, 30, 31, 32, 33, 0, 0, 0, 0, 0, 0, 0, 34, 35, 36, 37, + 38, 39, 40, 41, 42, 43, 44, 45, 46, 43, 47, 48, 49, 50, 51, 52, + 53, 54, 55, 56, 53, 57, 58, 59, 53, 0, 60, 61, 62, 63, 64, 65, + 66, 67, 68, 69, 70, 71, 72, 69, 0, 0, 73, 74, 75, 76, 77, 69, + 0, 0, 0, 0, 0, 0, 78, 0, 69, 69, 69, 0, 0, 0, 0, 0, + 0, 0, 79, 0, 80, 81, 82, 0, 83, 0, 29, 84, 85, 0, 0, 86, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 84, 0, 0, 87, 88, 89, 90, 91, 0, 0, 92, 93, + 85, 0, 0, 87, 0, 32, 0, 94, 95, 96, 97, 98, 0, 99, 100, 0, + 101, 0, 95, 102, 93, 103, 104, 69, 0, 0, 105, 0, 0, 0, 0, 106, + 0, 107, 108, 0, 32, 29, 24, 109, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 86, 0, 110, 92, 0, 111, 112, 113, + 114, 115, 0, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, + 129, 130, 131, 132, 133, 134, 0, 0, 135, 136, 0, 0, 0, 0, 0, 137, + 0, 138, 139, 14, 14, 14, 14, 140, 14, 14, 141, 142, 143, 144, 145, 146, + 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 0, 161, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 163, 164, 165, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 166, 0, 78, 0, 167, 89, 168, 168, 0, + 0, 0, 92, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 169, 170, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 171, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 173, 0, 0, 0, 0, 0, 174, 0, 0, 0, 0, 0, 0, 175, 176, + 0, 177, 0, 174, 0, 0, 178, 0, 0, 0, 179, 69, 0, 0, 180, 95, + 0, 89, 181, 0, 0, 0, 182, 89, 183, 184, 0, 99, 0, 0, 0, 185, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 172, 186, 68, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 187, 188, 189, 0, 0, 0, 190, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191, 0, 192, 172, + 193, 194, 69, 195, 0, 0, 0, 102, 196, 197, 197, 198, 199, 200, 201, 202, + 203, 204, 205, 69, 0, 0, 0, 109, 206, 207, 0, 0, 208, 209, 172, 92, + 69, 69, 69, 69, 84, 0, 120, 68, 0, 210, 32, 109, 211, 0, 212, 69, + 0, 0, 0, 0, 92, 213, 214, 68, 0, 24, 0, 215, 216, 217, 0, 90, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 94, 218, 219, 220, 69, 69, + 221, 222, 165, 0, 95, 223, 69, 224, 225, 226, 69, 69, 0, 227, 191, 0, + 228, 229, 230, 0, 0, 69, 0, 231, 0, 232, 233, 234, 235, 236, 69, 69, + 0, 0, 237, 69, 0, 238, 0, 239, 0, 240, 0, 241, 242, 69, 69, 69, + 69, 69, 69, 95, 0, 243, 244, 245, 0, 24, 85, 172, 138, 172, 173, 89, + 0, 0, 246, 88, 0, 0, 247, 248, 0, 111, 24, 89, 0, 0, 0, 249, + 250, 0, 251, 69, 252, 213, 0, 253, 34, 254, 255, 256, 257, 165, 258, 259, + 0, 0, 260, 251, 0, 0, 240, 69, 69, 69, 69, 69, 0, 233, 92, 69, + 0, 0, 261, 262, 0, 85, 213, 263, 29, 99, 264, 69, 69, 69, 69, 69, + 0, 68, 69, 69, 69, 0, 0, 265, 266, 267, 268, 69, 69, 269, 270, 271, + 0, 0, 24, 0, 0, 272, 0, 87, 138, 69, 69, 69, 69, 69, 0, 273, + 274, 275, 276, 277, 191, 278, 69, 69, 279, 280, 240, 281, 282, 138, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 87, 283, 284, 109, 69, 69, 285, 0, 286, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 69, 69, 69, + 0, 0, 0, 287, 0, 0, 0, 0, 0, 0, 263, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 172, 0, 0, 238, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 264, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 0, 85, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 87, 95, 288, 0, 95, 213, 289, 0, 0, 290, 291, 194, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 0, 85, 69, 69, 69, 69, + 69, 69, 0, 0, 109, 69, 69, 69, 0, 0, 292, 0, 293, 69, 69, 69, + 0, 0, 0, 294, 295, 263, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 90, 69, 69, 0, 103, 296, 0, 0, 0, 263, 69, + 0, 0, 0, 0, 0, 0, 0, 94, 0, 297, 0, 0, 0, 0, 0, 139, + 0, 0, 298, 69, 69, 69, 90, 90, 69, 69, 69, 299, 69, 69, 69, 69, + 0, 0, 111, 0, 76, 300, 301, 0, 302, 303, 304, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 305, 0, 0, 0, 0, 0, 0, 0, 0, 306, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 307, 308, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 95, 309, 69, 69, 69, 69, 69, 69, + 310, 311, 0, 312, 313, 69, 69, 69, 0, 314, 315, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 172, 104, 0, 226, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 172, 85, 69, 69, 69, 69, 69, 69, 172, 67, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 316, + 0, 0, 0, 0, 0, 0, 317, 69, 0, 0, 318, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 319, 0, 320, 69, 69, 66, 92, 69, 69, 69, 69, 69, 69, + 301, 321, 322, 323, 324, 325, 69, 326, 69, 69, 69, 69, 69, 69, 69, 69, + 301, 99, 0, 0, 90, 327, 328, 94, 329, 330, 14, 331, 332, 333, 69, 334, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 335, 69, 336, 337, 69, 338, 339, + 69, 170, 340, 69, 69, 69, 69, 341, 69, 342, 343, 344, 345, 301, 0, 109, + 69, 69, 172, 0, 69, 69, 346, 347, 0, 0, 0, 348, 0, 0, 85, 69, + 99, 0, 240, 0, 24, 349, 251, 69, 173, 350, 351, 69, 69, 69, 69, 69, + 0, 0, 90, 312, 69, 69, 69, 69, 0, 0, 0, 0, 352, 0, 0, 85, + 340, 0, 0, 0, 69, 69, 69, 69, 14, 14, 14, 14, 14, 14, 14, 193, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 353 +}; + +static RE_UINT8 re_east_asian_width_table_3[] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, + 1, 3, 2, 2, 3, 2, 2, 3, 3, 1, 3, 1, 2, 3, 3, 2, + 3, 3, 3, 3, 3, 1, 3, 3, 3, 3, 3, 1, 3, 3, 3, 3, + 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 3, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 3, 3, + 3, 3, 1, 1, 1, 1, 3, 1, 3, 3, 3, 1, 3, 3, 1, 1, + 3, 1, 3, 3, 1, 1, 1, 3, 3, 3, 3, 1, 3, 1, 3, 1, + 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 3, 1, 1, 1, 1, + 1, 3, 3, 3, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, + 3, 3, 3, 1, 3, 1, 1, 1, 3, 3, 3, 3, 1, 3, 1, 1, + 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 3, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, + 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 3, 1, 1, 3, 1, 3, 3, 3, 1, 3, 1, 1, + 3, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 3, 1, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, + 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, + 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 1, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, + 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, + 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, + 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, + 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, + 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, + 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, + 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, + 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, + 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, + 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, + 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 3, 1, 1, 3, 3, 3, 3, 1, 3, 3, 1, 1, 3, 3, 1, 1, + 3, 3, 3, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, + 3, 1, 3, 3, 1, 3, 1, 1, 1, 1, 1, 3, 1, 1, 3, 1, + 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, + 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 3, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 3, 1, 3, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 3, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 3, 3, 1, 1, 1, 3, 1, 1, 1, 1, 3, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 0, 0, 0, 0, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 3, 1, 3, 3, 1, 1, 1, 3, 3, 1, 1, 3, 1, 1, 1, 3, + 1, 3, 1, 1, 1, 3, 1, 1, 1, 1, 3, 1, 1, 3, 3, 3, + 3, 1, 1, 3, 1, 3, 1, 3, 3, 3, 3, 3, 3, 1, 3, 1, + 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 3, 3, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 3, 1, 1, 1, + 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 3, 3, 1, 1, 3, 3, 3, 3, 1, 1, 3, 3, 1, 1, 3, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 3, 3, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 3, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, + 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 3, 3, 1, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, + 1, 1, 3, 3, 1, 1, 3, 3, 1, 1, 1, 1, 3, 3, 1, 1, + 3, 3, 1, 1, 1, 1, 3, 3, 3, 1, 1, 3, 1, 1, 3, 3, + 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, + 1, 1, 1, 1, 1, 3, 3, 1, 1, 3, 1, 1, 1, 1, 3, 3, + 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 3, 1, 3, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 3, 3, 1, 3, 3, 3, 1, 3, 3, 3, 3, 1, 3, 3, 1, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, + 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 3, + 1, 1, 1, 1, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 0, 3, + 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 1, 3, 1, 1, 1, 1, 3, 3, 0, 3, 3, 3, 3, 3, + 3, 3, 0, 0, 3, 0, 3, 3, 3, 3, 0, 3, 3, 0, 3, 3, + 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, + 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 0, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, + 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, + 0, 0, 4, 4, 4, 4, 4, 4, 0, 0, 4, 4, 4, 4, 4, 4, + 0, 0, 4, 4, 4, 4, 4, 4, 0, 0, 4, 4, 4, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 0, 4, 4, 4, 4, 4, 4, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 3, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, + 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, + 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, + 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, + 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, + 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, + 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 3, + 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, + 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0 +}; + +RE_UINT32 re_get_east_asian_width(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = codepoint & 0x1F; + + v = re_east_asian_width_table_1[field_2]; + v = re_east_asian_width_table_2[(v << 5) | field_1]; + v = re_east_asian_width_table_3[(v << 5) | field_0]; + + return v; +} + +/* Emoji. */ +static RE_UINT8 re_emoji_table_1[] = { + 0, 1, 1, 1, 1, 1, 1, 1, 2, 3, 4, 1, 5, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 7, 8, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +}; + +static RE_UINT8 re_emoji_table_2[] = { + 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3, 4, 0, 0, 0, 0, 0, 0, 5, 0, 0, 6, 7, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0, 10, 11, + 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 32, 0, 0, 0, 0, 0, + 0, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 35, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 36, 37, 0, 0, 38, + 39, 40, 41, 0, 0, 0, 0, 0, 42, 43, 42, 42, 44, 42, 42, 45, + 42, 42, 42, 42, 42, 42, 42, 46, 42, 47, 48, 49, 50, 51, 52, 53, + 42, 42, 54, 0, 42, 42, 55, 56, 0, 0, 0, 0, 0, 0, 0, 57, + 0, 0, 0, 0, 0, 0, 0, 0, 58, 59, 60, 42, 42, 42, 42, 42, + 0, 0, 0, 61, 62, 42, 63, 64, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_emoji_table_3[] = { + 0, 0, 0, 0, 8, 4, 255, 3, 0, 66, 0, 0, 0, 0, 0, 16, + 0, 2, 0, 0, 4, 0, 0, 2, 0, 0, 240, 3, 0, 6, 0, 0, + 0, 0, 0, 12, 0, 1, 0, 0, 0, 128, 0, 0, 0, 254, 15, 7, + 4, 0, 0, 0, 0, 12, 64, 0, 1, 0, 0, 0, 0, 0, 0, 120, + 31, 64, 50, 33, 77, 196, 0, 7, 5, 255, 15, 128, 105, 1, 0, 200, + 0, 0, 252, 26, 131, 12, 3, 96, 48, 193, 26, 0, 0, 6, 191, 39, + 36, 191, 84, 32, 2, 1, 24, 0, 144, 80, 184, 0, 24, 0, 0, 0, + 0, 0, 224, 0, 2, 0, 1, 128, 0, 0, 48, 0, 224, 0, 0, 24, + 0, 0, 33, 0, 0, 0, 1, 32, 0, 0, 128, 2, 16, 0, 0, 0, + 0, 0, 3, 192, 0, 64, 254, 7, 192, 255, 255, 255, 6, 0, 0, 4, + 0, 128, 252, 7, 0, 0, 3, 0, 255, 255, 255, 255, 243, 255, 255, 255, + 255, 255, 207, 206, 255, 255, 185, 255, 255, 255, 255, 191, 255, 255, 255, 63, + 0, 126, 255, 255, 255, 128, 249, 7, 128, 60, 97, 0, 48, 1, 6, 16, + 28, 0, 14, 112, 10, 129, 8, 252, 255, 255, 0, 0, 63, 248, 231, 240, + 63, 26, 249, 31, 255, 15, 1, 0, 0, 240, 255, 255, 255, 255, 255, 247, + 191, 255, 255, 255, 0, 0, 255, 31, 255, 131, 255, 255, 127, 192, 255, 159, + 255, 3, 255, 1 +}; + +RE_UINT32 re_get_emoji(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_emoji_table_1[field_2]; + v = re_emoji_table_2[(v << 5) | field_1]; + v = re_emoji_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Emoji_Component. */ +static RE_UINT8 re_emoji_component_table_1[] = { + 0, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 1, 5, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +}; + +static RE_UINT8 re_emoji_component_table_2[] = { + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_emoji_component_table_3[] = { + 0, 0, 0, 0, 8, 4, 255, 3, 0, 32, 0, 0, 8, 0, 0, 0, + 0, 128, 0, 0, 192, 255, 255, 255, 0, 0, 0, 248, 0, 0, 15, 0, + 255, 255, 255, 255 +}; + +RE_UINT32 re_get_emoji_component(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_emoji_component_table_1[field_2]; + v = re_emoji_component_table_2[(v << 5) | field_1]; + v = re_emoji_component_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Emoji_Modifier. */ +RE_UINT32 re_get_emoji_modifier(RE_UINT32 codepoint) { + if (0x01F3FB <= codepoint && codepoint <= 0x01F3FF) + return 1; + + return 0; +} + +/* Emoji_Modifier_Base. */ +static RE_UINT8 re_emoji_modifier_base_table_1[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_emoji_modifier_base_table_2[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 5, 0, + 0, 0, 6, 7, 8, 9, 0, 0, 0, 0, 0, 10, 11, 0, 0, 0, + 0, 0, 12, 0, 0, 13, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 15, 16, 0, 17, 0, 18, 19, 0, + 0, 0, 0, 0, 0, 0, 20, 21, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_emoji_modifier_base_table_3[] = { + 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 2, 0, 60, 0, 0, + 32, 0, 0, 0, 156, 28, 0, 0, 204, 255, 1, 0, 192, 255, 255, 17, + 238, 128, 2, 0, 0, 4, 0, 0, 0, 0, 48, 4, 0, 0, 97, 0, + 224, 248, 0, 0, 8, 0, 112, 0, 1, 16, 0, 0, 0, 144, 0, 255, + 64, 0, 255, 115, 0, 0, 128, 0, 0, 0, 96, 11, 0, 224, 254, 63, + 56, 0, 0, 0, 0, 0, 255, 1 +}; + +RE_UINT32 re_get_emoji_modifier_base(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_emoji_modifier_base_table_1[field_2]; + v = re_emoji_modifier_base_table_2[(v << 5) | field_1]; + v = re_emoji_modifier_base_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Emoji_Presentation. */ +static RE_UINT8 re_emoji_presentation_table_1[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 6, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_emoji_presentation_table_2[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, + 4, 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0, 14, 15, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 17, 0, 0, 0, 0, 0, + 18, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 20, 0, 0, 21, + 22, 23, 24, 0, 0, 0, 0, 0, 25, 26, 25, 27, 28, 25, 29, 30, + 25, 31, 32, 25, 25, 25, 25, 33, 25, 34, 35, 36, 37, 18, 0, 38, + 25, 25, 39, 0, 25, 25, 40, 41, 0, 0, 0, 0, 0, 0, 0, 42, + 0, 0, 0, 0, 0, 0, 0, 0, 43, 44, 45, 25, 25, 25, 25, 25, + 0, 0, 0, 46, 47, 25, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_emoji_presentation_table_3[] = { + 0, 0, 0, 0, 0, 0, 0, 12, 0, 30, 9, 0, 0, 0, 0, 96, + 0, 0, 48, 0, 0, 255, 15, 0, 0, 0, 0, 128, 0, 0, 8, 0, + 2, 12, 0, 96, 48, 64, 16, 0, 0, 4, 44, 36, 32, 12, 0, 0, + 0, 1, 0, 0, 0, 80, 184, 0, 0, 0, 224, 0, 0, 0, 1, 128, + 0, 0, 0, 24, 0, 0, 33, 0, 16, 0, 0, 0, 0, 128, 0, 0, + 0, 64, 254, 7, 192, 255, 255, 255, 2, 0, 0, 4, 0, 128, 124, 7, + 0, 0, 3, 0, 255, 255, 255, 255, 1, 224, 191, 255, 255, 255, 255, 223, + 255, 255, 15, 0, 255, 135, 15, 0, 255, 255, 17, 255, 255, 255, 255, 127, + 253, 255, 255, 255, 255, 255, 255, 159, 255, 255, 255, 63, 0, 120, 255, 255, + 255, 0, 0, 4, 0, 0, 96, 0, 0, 0, 0, 248, 255, 255, 0, 0, + 63, 16, 231, 240, 0, 24, 240, 31, 255, 15, 1, 0, 0, 240, 255, 255, + 255, 255, 255, 247, 191, 255, 255, 255, 0, 0, 255, 31, 255, 131, 255, 255, + 127, 192, 255, 159, 255, 3, 255, 1 +}; + +RE_UINT32 re_get_emoji_presentation(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_emoji_presentation_table_1[field_2]; + v = re_emoji_presentation_table_2[(v << 5) | field_1]; + v = re_emoji_presentation_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Extended_Pictographic. */ +static RE_UINT8 re_extended_pictographic_table_1[] = { + 0, 1, 1, 1, 1, 1, 1, 1, 2, 3, 4, 1, 5, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 7, 8, 9, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +}; + +static RE_UINT8 re_extended_pictographic_table_2[] = { + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2, 3, 0, 0, 0, 0, 0, 0, 4, 0, 0, 5, 6, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 7, 8, 0, 0, 8, 0, 9, 10, + 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 12, 13, 14, + 15, 16, 16, 16, 17, 16, 16, 16, 18, 19, 20, 21, 22, 23, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 26, 0, 0, 0, 0, 0, + 0, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, 29, 9, 0, 30, 31, 32, 16, 33, + 34, 35, 36, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 37, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 38, 39, 16, 16, 16, 16, 16, + 16, 16, 40, 0, 16, 16, 16, 16, 0, 0, 0, 41, 0, 0, 42, 16, + 43, 0, 44, 0, 45, 46, 16, 16, 47, 48, 49, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 38 +}; + +static RE_UINT8 re_extended_pictographic_table_3[] = { + 0, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 16, 0, 2, 0, 0, + 4, 0, 0, 2, 0, 0, 240, 3, 0, 6, 0, 0, 0, 0, 0, 12, + 0, 1, 0, 0, 0, 128, 0, 0, 0, 254, 15, 7, 4, 0, 0, 0, + 0, 12, 64, 0, 1, 0, 0, 0, 0, 0, 0, 120, 191, 255, 247, 255, + 255, 255, 255, 255, 63, 0, 255, 255, 63, 255, 87, 32, 2, 1, 24, 0, + 144, 80, 184, 0, 248, 0, 0, 0, 0, 0, 224, 0, 2, 0, 1, 128, + 0, 0, 48, 0, 224, 0, 0, 24, 0, 0, 33, 0, 0, 0, 1, 32, + 0, 0, 128, 2, 0, 224, 0, 0, 0, 240, 3, 192, 0, 64, 254, 7, + 0, 224, 255, 255, 63, 0, 0, 0, 254, 255, 0, 4, 0, 128, 252, 247, + 0, 254, 255, 255, 255, 255, 255, 7, 255, 255, 255, 63, 192, 255, 255, 255, + 255, 255, 0, 0, 0, 0, 240, 255, 0, 0, 224, 255, 0, 240, 0, 0, + 0, 255, 0, 252, 0, 255, 0, 0, 0, 192, 255, 255, 0, 240, 255, 255, + 255, 255, 255, 247, 191, 255, 255, 255 +}; + +RE_UINT32 re_get_extended_pictographic(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_extended_pictographic_table_1[field_2]; + v = re_extended_pictographic_table_2[(v << 5) | field_1]; + v = re_extended_pictographic_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Extender. */ +static RE_UINT8 re_extender_table_1[] = { + 0, 1, 2, 3, 4, 4, 5, 6, 4, 4, 4, 4, 7, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 8, 9, 10, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 11, + 4, 12, 4, 13, 14, 15, 16, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 17, 18, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 19, 20, 21, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 +}; + +static RE_UINT8 re_extender_table_2[] = { + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 12, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 14, 0, 0, 15, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 8, + 0, 0, 0, 19, 0, 0, 20, 21, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 24, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 25, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_extender_table_3[] = { + 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 3, 0, 1, 0, 0, 0, + 0, 0, 0, 4, 0, 0, 2, 0, 0, 0, 0, 8, 0, 0, 32, 0, + 64, 0, 0, 0, 0, 4, 0, 0, 8, 0, 0, 0, 128, 0, 0, 0, + 0, 0, 64, 0, 32, 0, 0, 0, 0, 0, 62, 0, 0, 0, 0, 96, + 0, 0, 0, 112, 0, 16, 0, 0, 0, 128, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 32, 0, 0, 24, 0, 6, 0, 0, 0, 0, 64, 0, 0, + 0, 132, 0, 0, 0, 0, 12, 0, 192, 1, 0, 0, 0, 0, 0, 1, + 12, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 48, 112, 0, 0, 0 +}; + +RE_UINT32 re_get_extender(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_extender_table_1[field_2]; + v = re_extender_table_2[(v << 5) | field_1]; + v = re_extender_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* General_Category. */ +static RE_UINT8 re_general_category_table_1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 13, + 13, 13, 13, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 15, 16, 17, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 18, 19, 19, 20, 20, 20, 20, 20, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 13, 35, 13, 13, + 36, 37, 33, 33, 33, 33, 33, 33, 38, 33, 39, 40, 13, 13, 13, 13, + 13, 41, 13, 42, 33, 33, 33, 33, 33, 33, 33, 43, 44, 33, 33, 45, + 33, 33, 33, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 33, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 58, 13, 13, 13, 59, 60, 13, + 13, 13, 13, 61, 13, 13, 13, 13, 13, 13, 62, 63, 33, 33, 64, 33, + 13, 13, 13, 13, 65, 13, 13, 13, 66, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 67, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 68, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 68 +}; + +static RE_UINT16 re_general_category_table_2[] = { + 0, 1, 2, 3, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 7, 15, 16, 17, 18, 19, 20, 21, 22, 22, 22, 23, 24, 25, 26, 27, + 28, 29, 17, 7, 30, 7, 31, 7, 7, 32, 33, 17, 34, 35, 36, 37, + 38, 39, 40, 41, 39, 39, 42, 43, 44, 45, 46, 39, 39, 47, 48, 49, + 50, 51, 52, 53, 54, 39, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, + 97, 98, 99, 100, 101, 102, 103, 100, 104, 105, 106, 107, 108, 109, 110, 100, + 39, 111, 112, 113, 114, 28, 115, 116, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 117, 39, 118, 119, 120, 39, 121, 39, 122, 123, 124, 28, 28, 125, + 126, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 127, 128, 39, 39, 129, 130, 131, 132, 133, 39, 134, 135, 136, + 137, 39, 138, 139, 140, 141, 39, 142, 143, 144, 145, 146, 39, 147, 148, 149, + 150, 39, 151, 152, 153, 154, 155, 100, 156, 157, 158, 159, 160, 161, 39, 162, + 39, 163, 164, 165, 166, 167, 168, 169, 17, 170, 171, 172, 173, 171, 22, 22, + 7, 7, 7, 7, 174, 7, 7, 7, 175, 176, 177, 178, 179, 180, 181, 182, + 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, + 199, 199, 199, 199, 199, 199, 199, 199, 200, 201, 149, 202, 203, 204, 205, 206, + 149, 207, 208, 209, 210, 149, 149, 211, 149, 149, 149, 149, 149, 212, 213, 214, + 149, 149, 149, 215, 149, 149, 149, 149, 149, 149, 149, 216, 217, 149, 218, 219, + 149, 149, 149, 149, 149, 149, 149, 149, 199, 199, 199, 199, 220, 199, 221, 222, + 199, 199, 199, 199, 199, 199, 199, 199, 149, 223, 224, 225, 226, 149, 149, 149, + 28, 29, 17, 227, 7, 7, 7, 228, 17, 229, 39, 230, 231, 232, 232, 22, + 233, 234, 235, 100, 236, 149, 149, 237, 149, 149, 149, 149, 149, 149, 238, 239, + 240, 241, 97, 39, 242, 126, 39, 243, 244, 245, 39, 39, 246, 39, 149, 247, + 248, 249, 250, 149, 249, 251, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 149, 149, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 252, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 253, 149, 254, 165, 39, 39, 39, 39, 39, 39, 39, 39, + 255, 256, 7, 257, 258, 39, 39, 259, 260, 261, 7, 262, 263, 264, 265, 266, + 267, 268, 39, 269, 270, 271, 272, 273, 48, 274, 275, 276, 57, 277, 278, 279, + 39, 280, 281, 282, 39, 283, 284, 285, 286, 287, 288, 289, 17, 17, 39, 290, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 291, 292, 293, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 296, 39, 39, 297, 100, 298, 299, 300, 39, 39, 301, 302, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 303, 304, 39, 305, 39, 306, 307, + 308, 309, 310, 311, 39, 39, 39, 312, 313, 2, 314, 315, 316, 143, 317, 318, + 319, 320, 321, 100, 39, 39, 39, 322, 323, 324, 194, 325, 326, 327, 239, 328, + 100, 100, 100, 100, 276, 39, 329, 330, 39, 331, 332, 333, 334, 39, 335, 100, + 28, 336, 337, 39, 338, 339, 340, 341, 39, 342, 39, 343, 344, 345, 39, 346, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 231, 142, 347, 348, 349, 100, 100, + 350, 351, 352, 353, 143, 354, 100, 355, 356, 357, 100, 100, 39, 358, 359, 209, + 360, 361, 362, 363, 364, 100, 365, 366, 39, 367, 368, 369, 370, 371, 100, 100, + 39, 39, 372, 100, 28, 373, 17, 374, 39, 375, 376, 377, 378, 100, 100, 100, + 100, 100, 100, 379, 39, 380, 381, 382, 364, 383, 384, 385, 386, 385, 387, 231, + 388, 389, 390, 391, 160, 392, 393, 394, 395, 396, 397, 398, 160, 399, 400, 401, + 402, 403, 404, 100, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, + 39, 417, 418, 419, 39, 420, 421, 100, 100, 100, 100, 100, 39, 422, 423, 100, + 39, 424, 425, 426, 39, 427, 428, 429, 430, 431, 432, 100, 100, 100, 100, 100, + 39, 433, 100, 100, 100, 28, 17, 434, 435, 436, 437, 100, 100, 438, 439, 440, + 441, 442, 443, 39, 444, 445, 39, 139, 446, 100, 100, 100, 100, 100, 39, 447, + 448, 449, 450, 451, 452, 453, 100, 100, 454, 455, 456, 457, 458, 459, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 460, 461, 462, 463, 100, 100, 464, 465, 466, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 297, 100, 100, 100, + 194, 194, 194, 467, 39, 39, 39, 39, 39, 39, 468, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 385, 39, 39, 469, + 39, 470, 471, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 322, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 432, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 472, 473, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 139, 143, 474, 39, 143, 475, 476, 39, 477, 478, 479, 480, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 481, 482, 100, 100, 100, 100, + 100, 100, 28, 17, 483, 100, 100, 100, 39, 39, 484, 485, 486, 100, 100, 487, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 488, + 39, 39, 39, 39, 39, 39, 142, 489, 372, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 490, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 491, 492, 493, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 293, 100, 100, 100, 100, 100, 100, 100, 100, + 39, 39, 39, 494, 495, 496, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 149, 149, 149, 149, 149, 149, 149, 497, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 237, 100, 100, 22, 498, 499, 149, 149, 149, 500, 100, + 149, 149, 149, 149, 149, 149, 149, 238, 149, 501, 149, 502, 503, 504, 149, 208, + 149, 149, 505, 100, 100, 100, 506, 506, 149, 149, 507, 508, 100, 100, 100, 100, + 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 509, 510, 522, + 512, 523, 524, 525, 516, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 22, 537, 22, 538, 539, 540, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 541, 542, 100, 100, 100, 100, 100, 100, + 543, 544, 171, 545, 546, 100, 100, 100, 39, 547, 548, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 385, 549, 39, 550, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 385, 551, 100, 100, 100, 100, 100, 100, 385, 552, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 553, + 39, 39, 39, 39, 39, 39, 554, 100, 28, 555, 556, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 557, 209, 558, 100, 100, 559, 560, 100, 100, 100, 100, 100, 100, + 561, 562, 563, 564, 565, 566, 100, 567, 100, 100, 100, 100, 100, 100, 100, 100, + 149, 568, 149, 149, 237, 569, 570, 238, 571, 149, 149, 149, 149, 572, 100, 573, + 574, 575, 576, 577, 100, 100, 100, 100, 149, 149, 149, 149, 149, 149, 149, 578, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 579, 580, 149, 149, 149, 581, 149, 149, 582, 583, + 568, 149, 584, 149, 585, 586, 587, 100, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 237, 588, 589, 149, 590, 591, 149, 149, 149, 149, 592, 149, 149, 497, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 100, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 297, 39, 39, 39, 39, 39, 39, + 338, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 593, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 594, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 338, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 338, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 53, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 480, 100, 100, + 595, 596, 596, 596, 100, 100, 100, 100, 22, 22, 22, 22, 22, 22, 22, 597, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 598 +}; + +static RE_UINT8 re_general_category_table_3[] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 3, 3, 3, 4, 3, 3, 3, 5, 6, 3, 7, 3, 8, 3, 3, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 7, 7, 7, 3, + 3, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 5, 3, 6, 11, 12, + 11, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 5, 7, 6, 7, 1, + 2, 3, 4, 4, 4, 4, 14, 3, 11, 14, 15, 16, 7, 17, 14, 11, + 14, 7, 18, 18, 11, 13, 3, 3, 11, 18, 15, 19, 18, 18, 18, 3, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 7, 10, 10, 10, 10, 10, 10, 10, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 7, 13, 13, 13, 13, 13, 13, 13, 13, + 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, + 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, + 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, + 10, 13, 10, 13, 10, 13, 10, 13, 13, 10, 13, 10, 13, 10, 13, 10, + 13, 10, 13, 10, 13, 10, 13, 10, 13, 13, 10, 13, 10, 13, 10, 13, + 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, + 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, + 10, 13, 10, 13, 10, 13, 10, 13, 10, 10, 13, 10, 13, 10, 13, 13, + 13, 10, 10, 13, 10, 13, 10, 10, 13, 10, 10, 10, 13, 13, 10, 10, + 10, 10, 13, 10, 10, 13, 10, 10, 10, 13, 13, 13, 10, 10, 13, 10, + 10, 13, 10, 13, 10, 13, 10, 10, 13, 10, 13, 13, 10, 13, 10, 10, + 13, 10, 10, 10, 13, 10, 13, 10, 10, 13, 13, 15, 10, 13, 13, 13, + 15, 15, 15, 15, 10, 20, 13, 10, 20, 13, 10, 20, 13, 10, 13, 10, + 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 13, 10, 13, + 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, + 13, 10, 20, 13, 10, 13, 10, 10, 10, 13, 10, 13, 10, 13, 10, 13, + 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, + 10, 13, 10, 13, 13, 13, 13, 13, 13, 13, 10, 10, 13, 10, 10, 13, + 13, 10, 13, 10, 10, 10, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 15, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 11, 11, 11, 11, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 21, 21, 21, 21, 21, 11, 11, 11, 11, 11, 11, 11, 21, 11, 21, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 10, 13, 10, 13, 21, 11, 10, 13, 0, 0, 21, 13, 13, 13, 3, 10, + 0, 0, 0, 0, 11, 11, 10, 3, 10, 10, 10, 0, 10, 0, 10, 10, + 13, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 10, + 13, 13, 10, 10, 10, 13, 13, 13, 10, 13, 10, 13, 10, 13, 10, 13, + 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, + 13, 13, 13, 13, 10, 13, 7, 10, 13, 10, 10, 13, 13, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 10, 13, 14, 22, 22, 22, 22, 22, 23, 23, 10, 13, 10, 13, 10, 13, + 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, + 10, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 13, + 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, + 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, + 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 0, 0, 21, 3, 3, 3, 3, 3, 3, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 3, 8, 0, 0, 14, 14, 4, + 0, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 8, 22, + 3, 22, 22, 3, 22, 22, 3, 22, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 15, + 15, 15, 15, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 17, 17, 17, 17, 17, 17, 7, 7, 7, 3, 3, 4, 3, 3, 14, 14, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 3, 17, 3, 3, 3, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 21, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 3, 3, 15, 15, + 22, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 3, 15, 22, 22, 22, 22, 22, 22, 22, 17, 14, 22, + 22, 22, 22, 22, 22, 21, 21, 22, 22, 14, 22, 22, 22, 22, 15, 15, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 15, 15, 15, 14, 14, 15, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 17, + 15, 22, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 0, 0, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 21, 21, 14, 3, 3, 3, 21, 0, 0, 22, 4, 4, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 22, 22, 22, 22, 21, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 21, 22, 22, 22, 21, 22, 22, 22, 22, 22, 0, 0, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 22, 22, 22, 0, 0, 3, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 11, 15, 15, 15, 15, 15, 15, 0, + 17, 17, 0, 0, 0, 0, 0, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 21, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 17, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 24, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 22, 24, 22, 15, 24, 24, + 24, 22, 22, 22, 22, 22, 22, 22, 22, 24, 24, 24, 24, 22, 24, 24, + 15, 22, 22, 22, 22, 22, 22, 22, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 22, 22, 3, 3, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 3, 21, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 22, 24, 24, 0, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 15, + 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, + 15, 0, 15, 0, 0, 0, 15, 15, 15, 15, 0, 0, 22, 15, 24, 24, + 24, 22, 22, 22, 22, 0, 0, 24, 24, 0, 0, 24, 24, 22, 15, 0, + 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 15, 15, 0, 15, + 15, 15, 22, 22, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 15, 15, 4, 4, 18, 18, 18, 18, 18, 18, 14, 4, 15, 3, 22, 0, + 0, 22, 22, 24, 0, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 15, + 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, + 15, 0, 15, 15, 0, 15, 15, 0, 15, 15, 0, 0, 22, 0, 24, 24, + 24, 22, 22, 0, 0, 0, 0, 22, 22, 0, 0, 22, 22, 22, 0, 0, + 0, 22, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 0, 15, 0, + 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 22, 22, 15, 15, 15, 22, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 22, 22, 24, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, + 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, + 15, 0, 15, 15, 0, 15, 15, 15, 15, 15, 0, 0, 22, 15, 24, 24, + 24, 22, 22, 22, 22, 22, 0, 22, 22, 24, 0, 24, 24, 22, 0, 0, + 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 22, 22, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 3, 4, 0, 0, 0, 0, 0, 0, 0, 15, 22, 22, 22, 22, 22, 22, + 0, 22, 24, 24, 0, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 15, + 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, + 15, 0, 15, 15, 0, 15, 15, 15, 15, 15, 0, 0, 22, 15, 24, 22, + 24, 22, 22, 22, 22, 0, 0, 24, 24, 0, 0, 24, 24, 22, 0, 0, + 0, 0, 0, 0, 0, 22, 22, 24, 0, 0, 0, 0, 15, 15, 0, 15, + 15, 15, 22, 22, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 14, 15, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 22, 15, 0, 15, 15, 15, 15, 15, 15, 0, 0, 0, 15, 15, + 15, 0, 15, 15, 15, 15, 0, 0, 0, 15, 15, 0, 15, 0, 15, 15, + 0, 0, 0, 15, 15, 0, 0, 0, 15, 15, 15, 0, 0, 0, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 24, 24, + 22, 24, 24, 0, 0, 0, 24, 24, 24, 0, 24, 24, 24, 22, 0, 0, + 15, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 18, 18, 18, 14, 14, 14, 14, 14, 14, 4, 14, 0, 0, 0, 0, 0, + 22, 24, 24, 24, 22, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, + 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 22, 15, 22, 22, + 22, 24, 24, 24, 24, 0, 22, 22, 22, 0, 22, 22, 22, 22, 0, 0, + 0, 0, 0, 0, 0, 22, 22, 0, 15, 15, 15, 0, 0, 15, 0, 0, + 15, 15, 22, 22, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 3, 18, 18, 18, 18, 18, 18, 18, 14, + 15, 22, 24, 24, 3, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, + 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 0, 0, 22, 15, 24, 22, + 24, 24, 24, 24, 24, 0, 22, 24, 24, 0, 24, 24, 22, 22, 0, 0, + 0, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 0, 0, 15, 15, 0, + 15, 15, 22, 22, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 15, 15, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 22, 22, 24, 24, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, + 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 22, 22, 15, 24, 24, + 24, 22, 22, 22, 22, 0, 24, 24, 24, 0, 24, 24, 24, 22, 15, 14, + 0, 0, 0, 0, 15, 15, 15, 24, 18, 18, 18, 18, 18, 18, 18, 15, + 15, 15, 22, 22, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 14, 15, 15, 15, 15, 15, 15, + 0, 22, 24, 24, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 22, 0, 0, 0, 0, 24, + 24, 24, 22, 22, 22, 0, 22, 0, 24, 24, 24, 24, 24, 24, 24, 24, + 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 0, 24, 24, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 22, 15, 15, 22, 22, 22, 22, 22, 22, 22, 0, 0, 0, 0, 4, + 15, 15, 15, 15, 15, 15, 21, 22, 22, 22, 22, 22, 22, 22, 22, 3, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 15, 15, 0, 15, 0, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 0, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 22, 15, 15, 22, 22, 22, 22, 22, 22, 22, 22, 22, 15, 0, 0, + 15, 15, 15, 15, 15, 0, 21, 0, 22, 22, 22, 22, 22, 22, 22, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 15, 15, 15, 15, + 15, 14, 14, 14, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 14, 3, 14, 14, 14, 22, 22, 14, 14, 14, 14, 14, 14, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 14, 22, 14, 22, 14, 22, 5, 6, 5, 6, 24, 24, + 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, + 0, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 24, + 22, 22, 22, 22, 22, 3, 22, 22, 15, 15, 15, 15, 15, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 0, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 0, 14, 14, + 14, 14, 14, 14, 14, 14, 22, 14, 14, 14, 14, 14, 14, 0, 14, 14, + 3, 3, 3, 3, 3, 14, 14, 14, 14, 3, 3, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 24, 24, 22, 22, 22, + 22, 24, 22, 22, 22, 22, 22, 22, 24, 22, 22, 24, 24, 22, 22, 15, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 3, 3, 3, 3, + 15, 15, 15, 15, 15, 15, 24, 24, 22, 22, 15, 15, 15, 15, 22, 22, + 22, 15, 24, 24, 24, 15, 15, 24, 24, 24, 24, 24, 24, 24, 15, 15, + 15, 22, 22, 22, 22, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 22, 24, 24, 22, 22, 24, 24, 24, 24, 24, 24, 22, 15, 24, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 24, 24, 24, 22, 14, 14, + 10, 10, 10, 10, 10, 10, 0, 10, 0, 0, 0, 0, 0, 10, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 3, 21, 13, 13, 13, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 0, 15, 0, 15, 15, 15, 15, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 0, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 0, + 15, 0, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 0, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 22, 22, 22, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 0, 0, 13, 13, 13, 13, 13, 13, 0, 0, + 8, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 3, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 2, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 5, 6, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 3, 3, 3, 25, 25, + 25, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 22, 22, 22, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 22, 22, 24, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 22, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, + 15, 0, 22, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 22, 22, 24, 22, 22, 22, 22, 22, 22, 22, 24, 24, + 24, 24, 24, 24, 24, 24, 22, 24, 24, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 3, 3, 3, 21, 3, 3, 3, 4, 15, 22, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, + 3, 3, 3, 3, 3, 3, 8, 3, 3, 3, 3, 22, 22, 22, 17, 22, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 21, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 22, 22, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 22, 15, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, + 22, 22, 22, 24, 24, 24, 24, 22, 22, 24, 24, 24, 0, 0, 0, 0, + 24, 24, 22, 24, 24, 24, 24, 24, 24, 22, 22, 22, 0, 0, 0, 0, + 14, 0, 0, 0, 3, 3, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, + 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 0, 0, 0, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 22, 22, 24, 24, 22, 0, 0, 3, 3, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 24, 22, 24, 22, 22, 22, 22, 22, 22, 22, 0, + 22, 24, 22, 24, 24, 22, 22, 22, 22, 22, 22, 22, 22, 24, 24, 24, + 24, 24, 24, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 0, 0, 22, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 3, 3, 3, 3, 3, 3, 3, 21, 3, 3, 3, 3, 3, 3, 0, 0, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 22, 22, 22, 22, 24, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 22, 24, 22, 22, 22, 22, 22, 24, 22, 24, 24, 24, + 24, 24, 22, 24, 24, 15, 15, 15, 15, 15, 15, 15, 15, 0, 3, 3, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 3, 3, 3, 3, + 3, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 14, 14, 14, 14, 14, 14, 14, 14, 14, 3, 3, 3, + 22, 22, 24, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 24, 22, 22, 22, 22, 24, 24, 22, 22, 24, 22, 22, 22, 15, 15, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 22, 24, 22, 22, 24, 24, 24, 22, 24, 22, + 22, 22, 24, 24, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, + 15, 15, 15, 15, 24, 24, 24, 24, 24, 24, 24, 24, 22, 22, 22, 22, + 22, 22, 22, 22, 24, 24, 22, 22, 0, 0, 0, 3, 3, 3, 3, 3, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 15, 15, 15, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 21, 21, 21, 21, 21, 21, 3, 3, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 10, 13, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 10, 10, 10, + 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, + 22, 22, 22, 3, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 24, 22, 22, 22, 22, 22, 22, 22, 15, 15, 15, 15, 22, 15, 15, + 15, 15, 15, 15, 22, 15, 15, 24, 22, 22, 15, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 21, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 21, 21, 21, 21, 21, + 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, + 10, 13, 10, 13, 10, 13, 13, 13, 13, 13, 13, 13, 13, 13, 10, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 10, 10, 10, 10, 10, 10, 10, 10, + 13, 13, 13, 13, 13, 13, 0, 0, 10, 10, 10, 10, 10, 10, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 10, 10, 10, 10, 10, 10, 10, 10, + 13, 13, 13, 13, 13, 13, 13, 13, 10, 10, 10, 10, 10, 10, 10, 10, + 13, 13, 13, 13, 13, 13, 0, 0, 10, 10, 10, 10, 10, 10, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 0, 10, 0, 10, 0, 10, 0, 10, + 13, 13, 13, 13, 13, 13, 13, 13, 10, 10, 10, 10, 10, 10, 10, 10, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 20, 20, 20, 20, 20, 20, 20, 20, + 13, 13, 13, 13, 13, 13, 13, 13, 20, 20, 20, 20, 20, 20, 20, 20, + 13, 13, 13, 13, 13, 13, 13, 13, 20, 20, 20, 20, 20, 20, 20, 20, + 13, 13, 13, 13, 13, 0, 13, 13, 10, 10, 10, 10, 20, 11, 13, 11, + 11, 11, 13, 13, 13, 0, 13, 13, 10, 10, 10, 10, 20, 11, 11, 11, + 13, 13, 13, 13, 0, 0, 13, 13, 10, 10, 10, 10, 0, 11, 11, 11, + 13, 13, 13, 13, 13, 13, 13, 13, 10, 10, 10, 10, 10, 11, 11, 11, + 0, 0, 13, 13, 13, 0, 13, 13, 10, 10, 10, 10, 20, 11, 11, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 17, 17, 17, 17, 17, + 8, 8, 8, 8, 8, 8, 3, 3, 16, 19, 5, 16, 16, 19, 5, 16, + 3, 3, 3, 3, 3, 3, 3, 3, 26, 27, 17, 17, 17, 17, 17, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 16, 19, 3, 3, 3, 3, 12, + 12, 3, 3, 3, 7, 5, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 7, 3, 12, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, + 17, 17, 17, 17, 17, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 18, 21, 0, 0, 18, 18, 18, 18, 18, 18, 7, 7, 7, 5, 6, 21, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 7, 7, 7, 5, 6, 0, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, + 23, 22, 23, 23, 23, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 10, 14, 14, 14, 14, 10, 14, 14, 13, 10, 10, 10, 13, 13, + 10, 10, 10, 13, 14, 10, 14, 14, 7, 10, 10, 10, 10, 10, 14, 14, + 14, 14, 14, 14, 10, 14, 10, 14, 10, 14, 10, 10, 10, 10, 14, 13, + 10, 10, 10, 10, 13, 15, 15, 15, 15, 13, 14, 14, 13, 13, 10, 10, + 7, 7, 7, 7, 7, 10, 13, 13, 13, 13, 14, 7, 14, 14, 13, 14, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 10, 13, 25, 25, 25, 25, 18, 14, 14, 0, 0, 0, 0, + 7, 7, 7, 7, 7, 14, 14, 14, 14, 14, 7, 7, 14, 14, 14, 14, + 7, 14, 14, 7, 14, 14, 7, 14, 14, 14, 14, 14, 14, 14, 7, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 7, + 14, 14, 7, 14, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 14, 14, 14, 14, 14, 14, 14, 14, 5, 6, 5, 6, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 7, 7, 14, 14, 14, 14, 14, 14, 14, 5, 6, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 7, 7, 7, + 7, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 7, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 7, 7, 7, 7, 7, 7, 7, 7, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 5, 6, 5, 6, 5, 6, 5, 6, + 5, 6, 5, 6, 5, 6, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 7, 7, 7, 7, 7, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, + 6, 5, 6, 5, 6, 5, 6, 5, 6, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 5, 6, 5, 6, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 5, 6, 7, 7, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 14, 14, 7, 7, 7, 7, 7, 7, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 10, 13, 10, 10, 10, 13, 13, 10, 13, 10, 13, 10, 13, 10, 10, 10, + 10, 13, 10, 13, 13, 10, 13, 13, 13, 13, 13, 13, 21, 21, 10, 10, + 10, 13, 10, 13, 13, 14, 14, 14, 14, 14, 14, 10, 13, 10, 13, 22, + 22, 22, 10, 13, 0, 0, 0, 0, 0, 3, 3, 3, 3, 18, 3, 3, + 13, 13, 13, 13, 13, 13, 0, 13, 0, 0, 0, 0, 0, 13, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 21, + 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 0, + 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 0, + 3, 3, 16, 19, 16, 19, 3, 3, 3, 16, 19, 3, 16, 19, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 8, 3, 3, 8, 3, 16, 19, 3, 3, + 16, 19, 5, 6, 5, 6, 5, 6, 5, 6, 3, 3, 3, 3, 3, 21, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 8, 8, 3, 3, 3, 3, + 8, 3, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 14, 14, 3, 3, 3, 5, 6, 5, 6, 5, 6, 5, 6, 8, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 2, 3, 3, 3, 14, 21, 15, 25, 5, 6, 5, 6, 5, 6, 5, 6, + 5, 6, 14, 14, 5, 6, 5, 6, 5, 6, 5, 6, 8, 5, 6, 6, + 14, 25, 25, 25, 25, 25, 25, 25, 25, 25, 22, 22, 22, 22, 24, 24, + 8, 21, 21, 21, 21, 21, 14, 14, 25, 25, 25, 21, 15, 3, 14, 14, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 0, 0, 22, 22, 11, 11, 21, 21, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 3, 21, 21, 21, 15, + 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, + 14, 14, 18, 18, 18, 18, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 18, 18, 18, 18, 18, 18, 18, 18, + 14, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 21, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 21, 3, 3, 3, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 15, 15, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 15, 22, + 23, 23, 23, 3, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 3, 21, + 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, + 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 21, 21, 22, 22, + 15, 15, 15, 15, 15, 15, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 22, 22, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 11, 11, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, + 13, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, + 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, + 21, 13, 13, 13, 13, 13, 13, 13, 13, 10, 13, 10, 13, 10, 10, 13, + 10, 13, 10, 13, 10, 13, 10, 13, 21, 11, 11, 10, 13, 10, 13, 15, + 10, 13, 10, 13, 13, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, + 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 10, 10, 10, 10, 13, + 10, 10, 10, 10, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, 10, 13, + 10, 13, 10, 13, 10, 10, 10, 10, 13, 10, 13, 10, 10, 13, 0, 0, + 10, 13, 0, 13, 0, 13, 10, 13, 10, 13, 10, 13, 10, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 21, 21, 21, 10, 13, 15, 21, 21, 13, 15, 15, 15, 15, 15, + 15, 15, 22, 15, 15, 15, 22, 15, 15, 15, 15, 22, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 24, 24, 22, 22, 24, 14, 14, 14, 14, 22, 0, 0, 0, + 18, 18, 18, 18, 18, 18, 14, 14, 4, 14, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, + 24, 24, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 22, 22, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 15, 15, 15, 15, 15, 15, 3, 3, 3, 15, 3, 15, 15, 22, + 15, 15, 15, 15, 15, 15, 22, 22, 22, 22, 22, 22, 22, 22, 3, 3, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 24, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 22, 24, 24, 22, 22, 22, 22, 24, 24, 22, 22, 24, 24, + 24, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 21, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 3, 3, + 15, 15, 15, 15, 15, 22, 21, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 15, 15, 15, 15, 15, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 22, 22, 22, 22, 22, 22, 24, + 24, 22, 22, 24, 24, 22, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 22, 15, 15, 15, 15, 15, 15, 15, 15, 22, 24, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 3, 3, 3, 3, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 21, 15, 15, 15, 15, 15, 15, 14, 14, 14, 15, 24, 22, 24, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 22, 15, 22, 22, 22, 15, 15, 22, 22, 15, 15, 15, 15, 15, 22, 22, + 15, 22, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 21, 3, 3, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 24, 22, 22, 24, 24, + 3, 3, 15, 21, 21, 24, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 0, + 0, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 11, 21, 21, 21, 21, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 21, 11, 11, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 15, 15, 15, 24, 24, 22, 24, 24, 22, 24, 24, 3, 24, 22, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 15, 22, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 7, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 0, 15, 0, + 15, 15, 0, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 6, 5, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 14, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 4, 14, 14, 14, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 3, 3, 3, 3, 3, 3, 3, 5, 6, 3, 0, 0, 0, 0, 0, 0, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 3, 8, 8, 12, 12, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, + 6, 5, 6, 5, 6, 3, 3, 5, 6, 3, 3, 3, 3, 12, 12, 12, + 3, 3, 3, 0, 3, 3, 3, 3, 8, 5, 6, 5, 6, 5, 6, 3, + 3, 3, 7, 8, 7, 7, 7, 0, 3, 4, 3, 3, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 17, + 0, 3, 3, 3, 4, 3, 3, 3, 5, 6, 3, 7, 3, 8, 3, 3, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 7, 7, 7, 3, + 11, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 5, 7, 6, 7, 5, + 6, 3, 5, 6, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 21, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 21, 21, + 0, 0, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, + 0, 0, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 15, 0, 0, 0, + 4, 4, 7, 11, 14, 4, 4, 0, 14, 7, 7, 7, 7, 14, 14, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 14, 14, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 0, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, + 3, 3, 3, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 18, 18, 18, 18, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 18, 18, 14, 14, 14, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 22, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 22, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, + 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 25, 15, 15, 15, 15, 15, 15, 15, 15, 25, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 22, 22, 22, 22, 22, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 3, + 15, 15, 15, 15, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, + 3, 25, 25, 25, 25, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, + 10, 10, 10, 0, 10, 10, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 0, 13, 13, 13, 13, 13, 13, 13, 0, 13, 13, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 21, 21, 21, 21, 21, 21, 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 0, 0, 15, 0, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 0, 15, 15, 0, 0, 0, 15, 0, 0, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 0, 3, 18, 18, 18, 18, 18, 18, 18, 18, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 14, 14, 18, 18, 18, 18, 18, 18, 18, + 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 0, 15, 15, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 18, 18, 18, 18, 18, 18, 0, 0, 0, 3, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 3, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 18, 18, 15, 15, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 15, 22, 22, 22, 0, 22, 22, 0, 0, 0, 0, 0, 22, 22, 22, 22, + 15, 15, 15, 15, 0, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 0, 0, 22, 22, 22, 0, 0, 0, 0, 22, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 18, 18, 3, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 18, 18, 18, + 15, 15, 15, 15, 15, 15, 15, 15, 14, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 22, 22, 0, 0, 0, 0, 18, 18, 18, 18, 18, + 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, + 15, 15, 15, 15, 22, 22, 22, 22, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 15, 15, 15, 15, 21, 15, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 0, 0, 0, 22, 22, 22, 22, 22, 8, 21, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 22, 22, 8, 0, 0, + 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 22, 22, 22, + 18, 18, 18, 18, 18, 18, 18, 15, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 18, 18, 18, 18, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 22, 22, 22, 22, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 24, 22, 24, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 3, 3, 3, 3, 3, 3, 3, 0, 0, + 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 22, 15, 15, 22, 22, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 24, 24, 24, 22, 22, 22, 22, 24, 24, 22, 22, 3, 3, 17, 3, 3, + 3, 3, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 22, 22, 22, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 22, 22, 22, 22, 22, 24, 22, 22, 22, + 22, 22, 22, 22, 22, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 3, 3, 3, 3, 15, 24, 24, 15, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 22, 3, 3, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 24, 24, 24, 22, 22, 22, 22, 22, 22, 22, 22, 22, 24, + 24, 15, 15, 15, 15, 3, 3, 3, 3, 22, 22, 22, 22, 3, 24, 22, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 15, 3, 15, 3, 3, 3, + 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 24, 24, 24, 22, + 22, 22, 24, 24, 22, 24, 22, 22, 3, 3, 3, 3, 3, 3, 22, 15, + 15, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 0, 15, 0, 15, 15, 15, 15, 0, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 3, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 22, + 24, 24, 24, 22, 22, 22, 22, 22, 22, 22, 22, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 22, 22, 24, 24, 0, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 15, + 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, + 15, 0, 15, 15, 0, 15, 15, 15, 15, 15, 0, 22, 22, 15, 24, 24, + 22, 24, 24, 24, 24, 0, 0, 24, 24, 0, 0, 24, 24, 24, 0, 0, + 15, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 15, 15, 15, + 15, 15, 24, 24, 0, 0, 22, 22, 22, 22, 22, 22, 22, 0, 0, 0, + 22, 22, 22, 22, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 0, 0, 15, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 0, 15, 24, 24, 24, 22, 22, 22, 22, 22, + 22, 0, 24, 0, 0, 24, 0, 24, 24, 24, 24, 0, 24, 24, 22, 24, + 22, 15, 22, 15, 3, 3, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, + 0, 22, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 24, 24, 24, 22, 22, 22, 22, 22, 22, 22, 22, + 24, 24, 22, 22, 22, 24, 22, 15, 15, 15, 15, 3, 3, 3, 3, 3, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 0, 3, 22, 15, + 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 24, 24, 24, 22, 22, 22, 22, 22, 22, 24, 22, 24, 24, 24, 24, 22, + 22, 24, 22, 22, 15, 15, 3, 15, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 24, + 24, 24, 22, 22, 22, 22, 0, 0, 24, 24, 24, 24, 22, 22, 24, 22, + 22, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 15, 15, 15, 15, 22, 22, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 24, 24, 24, 22, 22, 22, 22, 22, 22, 22, 22, 24, 24, 22, 24, 22, + 22, 3, 3, 3, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 22, 24, 22, 24, 24, + 22, 22, 22, 22, 22, 22, 24, 22, 15, 3, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 22, 24, 22, + 24, 24, 22, 22, 22, 22, 24, 22, 22, 22, 22, 22, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 18, 3, 3, 3, 14, + 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 24, 24, 24, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 24, 22, 22, 3, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, + 15, 15, 15, 15, 15, 15, 15, 0, 0, 15, 0, 0, 15, 15, 15, 15, + 15, 15, 15, 15, 0, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 24, 24, 24, 24, 24, 24, 0, 24, 24, 0, 0, 22, 22, 24, 22, 15, + 24, 15, 24, 22, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 24, 24, 24, 22, 22, 22, 22, 0, 0, 22, 22, 24, 24, 24, 24, + 22, 15, 3, 15, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 22, 22, 22, 22, 22, 22, 24, 15, 22, 22, 22, 22, 3, + 3, 3, 3, 3, 3, 3, 3, 22, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 22, 22, 22, 22, 22, 22, 24, 24, 22, 22, 22, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 24, 22, 22, 3, 3, 3, 15, 3, 3, + 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 24, + 22, 22, 22, 22, 22, 22, 22, 0, 22, 22, 22, 22, 22, 22, 24, 22, + 15, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, + 3, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 0, 0, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 0, 24, 22, 22, 22, 22, 22, 22, + 22, 24, 22, 22, 24, 22, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 0, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 22, 22, 22, 22, 22, 22, 0, 0, 0, 22, 0, 22, 22, 0, 22, + 22, 22, 22, 22, 22, 22, 15, 22, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 0, 15, 15, 0, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 24, 24, 24, 24, 24, 0, + 22, 22, 0, 24, 24, 22, 24, 22, 15, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 22, 22, 24, 24, 3, 3, 0, 0, 0, 0, 0, 0, 0, + 22, 22, 15, 24, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 24, 24, 22, 22, 22, 22, 22, 0, 0, 0, 24, 24, + 22, 24, 22, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 22, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 14, 14, 14, 14, 14, 14, 14, 14, 4, 4, 4, + 4, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 0, + 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 22, 15, 15, 15, 15, 15, 15, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 24, 24, 24, 22, 22, 22, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 3, 3, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, + 22, 22, 22, 22, 22, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 22, 22, 22, 22, 22, 22, 22, 3, 3, 3, 3, 3, 14, 14, 14, 14, + 21, 21, 21, 21, 3, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 18, 18, 18, 18, 18, + 18, 18, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 21, 21, 21, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 21, 21, 3, 3, 3, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 3, 3, 3, 3, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 22, + 15, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 0, 0, 0, 0, 0, 22, + 22, 22, 22, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 3, 21, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 24, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 21, 21, 21, 21, 0, 21, 21, 21, 21, 21, 21, 21, 0, 21, 21, 0, + 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 14, 22, 22, 3, + 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 0, 0, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 0, 0, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 24, 24, 22, 22, 22, 14, 14, 14, 24, 24, 24, + 24, 24, 24, 17, 17, 17, 17, 17, 17, 17, 17, 22, 22, 22, 22, 22, + 22, 22, 22, 14, 14, 22, 22, 22, 22, 22, 22, 22, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 22, 22, 22, 22, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 22, 22, 22, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 13, 13, + 13, 13, 13, 13, 13, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 10, 0, 10, 10, + 0, 0, 10, 0, 0, 10, 10, 0, 0, 10, 10, 10, 10, 0, 10, 10, + 10, 10, 10, 10, 10, 10, 13, 13, 13, 13, 0, 13, 0, 13, 13, 13, + 13, 13, 13, 13, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 10, 10, 0, 10, 10, 10, 10, 0, 0, 10, 10, 10, + 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 0, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 10, 10, 0, 10, 10, 10, 10, 0, + 10, 10, 10, 10, 10, 0, 10, 0, 0, 0, 10, 10, 10, 10, 10, 10, + 10, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 10, 10, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 13, 13, 13, 13, 13, 13, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 7, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 7, 13, 13, 13, 13, + 13, 13, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 7, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 7, 13, 13, 13, 13, 13, 13, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 7, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 7, + 13, 13, 13, 13, 13, 13, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 7, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 7, 13, 13, 13, 13, 13, 13, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 7, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 7, 13, 13, 13, 13, 13, 13, 10, 13, 0, 0, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 14, 14, 14, 14, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 14, 14, 14, + 14, 14, 14, 14, 14, 22, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 22, 14, 14, 3, 3, 3, 3, 3, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 22, 22, 22, 22, + 0, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 15, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, + 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 22, 22, 22, 22, 22, 22, 22, 0, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 0, 0, 22, 22, 22, 22, 22, + 22, 22, 0, 22, 22, 0, 22, 22, 22, 22, 22, 0, 0, 0, 0, 0, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, + 22, 22, 22, 22, 22, 22, 22, 21, 21, 21, 21, 21, 21, 21, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 15, 14, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 22, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 22, 22, 22, 22, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 4, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 21, 22, 22, 22, 22, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 22, 22, + 15, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 3, + 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 0, 15, 15, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, + 15, 15, 15, 15, 15, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 22, 22, 22, 22, 22, 22, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 22, 22, 22, 22, 22, 22, 22, 21, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 3, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 14, 18, 18, 18, + 4, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 14, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, + 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 0, 15, 15, 0, 15, 0, 0, 15, 0, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 0, 15, 15, 15, 15, 0, 15, 0, 15, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, 0, 15, 0, 15, 0, 15, 0, 15, 15, 15, + 0, 15, 15, 0, 15, 0, 0, 15, 0, 15, 0, 15, 0, 15, 0, 15, + 0, 15, 15, 0, 15, 0, 0, 15, 15, 15, 15, 0, 15, 15, 15, 15, + 15, 15, 15, 0, 15, 15, 15, 15, 0, 15, 15, 15, 15, 0, 15, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, + 0, 15, 15, 15, 0, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, + 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 11, 11, 11, 11, 11, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, + 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 0, 0 +}; + +RE_UINT32 re_get_general_category(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = codepoint & 0x1F; + + v = re_general_category_table_1[field_2]; + v = re_general_category_table_2[(v << 5) | field_1]; + v = re_general_category_table_3[(v << 5) | field_0]; + + return v; +} + +/* Graph. */ +static RE_UINT8 re_graph_table_1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 15, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 16, 17, 17, 13, 13, 13, 13, 13, 13, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 17, 30, 13, 31, 13, 13, + 32, 33, 17, 17, 17, 17, 17, 17, 34, 17, 35, 36, 13, 13, 13, 13, + 13, 37, 13, 38, 17, 17, 17, 17, 17, 17, 17, 39, 40, 17, 17, 41, + 17, 17, 17, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 17, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 54, 13, 13, 13, 55, 56, 13, + 13, 13, 13, 57, 13, 13, 13, 13, 13, 13, 58, 59, 17, 17, 60, 17, + 13, 13, 13, 13, 61, 13, 13, 13, 62, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 63, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 64, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 64 +}; + +static RE_UINT16 re_graph_table_2[] = { + 0, 1, 2, 3, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 5, 6, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 7, 8, 2, 9, 2, 10, 11, + 2, 2, 2, 2, 2, 2, 2, 2, 12, 2, 13, 2, 2, 14, 2, 15, + 2, 16, 17, 18, 19, 2, 2, 2, 2, 2, 2, 2, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 29, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 39, 43, 44, 45, 39, 2, 46, 47, 48, 49, 50, 51, + 1, 52, 53, 0, 54, 55, 56, 0, 2, 2, 57, 58, 59, 60, 61, 0, + 2, 2, 2, 2, 2, 2, 62, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 63, 2, 64, 65, 66, 2, 67, 2, 15, 68, 69, 2, 2, 70, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 71, 2, 2, 72, 73, 74, 75, 76, 2, 2, 77, 78, + 69, 2, 2, 72, 2, 18, 2, 79, 3, 80, 81, 82, 2, 83, 84, 2, + 85, 2, 3, 86, 78, 87, 88, 0, 2, 2, 89, 2, 2, 2, 2, 90, + 2, 91, 92, 2, 18, 15, 10, 93, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 70, 2, 94, 77, 2, 95, 96, 97, + 98, 99, 3, 100, 101, 2, 102, 103, 2, 2, 2, 2, 83, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 104, 105, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 106, 107, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 108, 2, 62, 2, 109, 74, 110, 110, 2, + 2, 2, 77, 0, 111, 2, 2, 75, 2, 2, 2, 2, 2, 2, 79, 112, + 1, 2, 1, 2, 8, 2, 2, 2, 113, 7, 2, 2, 114, 2, 2, 115, + 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 116, 2, 117, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 118, 2, 2, 2, 2, 2, 119, 2, 2, 2, 2, 2, 2, 120, 121, + 2, 122, 2, 119, 2, 2, 123, 2, 2, 2, 124, 68, 2, 2, 125, 3, + 2, 74, 126, 2, 2, 2, 127, 74, 128, 129, 2, 83, 2, 2, 2, 130, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 131, 132, 53, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 87, 2, 2, 69, 0, 133, 134, 135, 2, 2, 2, 136, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 137, 2, 138, 112, + 69, 2, 139, 140, 2, 2, 2, 86, 1, 2, 2, 2, 2, 3, 141, 142, + 143, 144, 145, 0, 2, 2, 2, 93, 146, 147, 2, 2, 101, 148, 112, 77, + 0, 0, 0, 0, 68, 2, 103, 53, 2, 149, 18, 93, 150, 2, 151, 0, + 2, 2, 2, 2, 77, 152, 153, 53, 2, 10, 2, 154, 155, 156, 2, 75, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 74, 79, 157, 158, 159, 0, 0, + 160, 161, 107, 2, 3, 162, 0, 163, 164, 165, 0, 0, 2, 166, 137, 2, + 167, 168, 169, 2, 2, 0, 2, 170, 2, 171, 172, 173, 174, 175, 0, 0, + 2, 2, 176, 0, 2, 177, 2, 178, 2, 179, 2, 180, 181, 0, 0, 0, + 0, 0, 0, 3, 2, 182, 183, 184, 2, 10, 69, 112, 104, 112, 118, 74, + 2, 2, 185, 73, 2, 2, 186, 187, 2, 95, 10, 74, 2, 2, 2, 188, + 189, 2, 190, 0, 191, 152, 2, 192, 20, 193, 194, 195, 196, 107, 197, 198, + 2, 2, 199, 190, 2, 2, 179, 0, 0, 0, 0, 0, 2, 172, 77, 0, + 2, 2, 200, 201, 2, 69, 152, 202, 15, 83, 203, 0, 0, 0, 0, 0, + 2, 53, 0, 0, 0, 2, 2, 204, 205, 206, 207, 0, 0, 208, 4, 209, + 2, 2, 10, 2, 2, 210, 2, 72, 104, 0, 0, 0, 0, 0, 2, 211, + 212, 213, 214, 116, 137, 215, 0, 0, 216, 217, 179, 218, 219, 104, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 72, 220, 221, 93, 0, 0, 222, 2, 223, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 69, 0, 0, 0, + 2, 2, 2, 224, 2, 2, 2, 2, 2, 2, 202, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 2, 2, 177, + 2, 2, 79, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 93, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 203, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2, 69, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 72, 3, 225, 2, 3, 152, 226, 2, 2, 227, 228, 229, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 69, 0, 0, 0, 0, + 0, 0, 2, 2, 93, 0, 0, 0, 2, 2, 230, 2, 231, 0, 0, 232, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 119, + 2, 2, 2, 2, 2, 2, 79, 233, 176, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 235, 236, 237, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 53, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 238, 239, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 69, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 75, 0, 0, 2, 87, 117, 2, 2, 2, 202, 0, + 2, 2, 2, 2, 2, 2, 2, 79, 2, 240, 2, 2, 2, 2, 2, 105, + 2, 2, 241, 0, 0, 0, 75, 75, 2, 2, 74, 72, 0, 0, 0, 0, + 2, 2, 95, 2, 60, 242, 243, 2, 244, 245, 246, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 247, 2, 2, 2, 2, 2, 2, 2, 2, 248, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 249, 250, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3, 251, 0, 0, 0, 0, 0, 0, + 252, 253, 2, 254, 255, 0, 0, 0, 2, 256, 257, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 112, 88, 2, 165, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 112, 69, 0, 0, 0, 0, 0, 0, 112, 52, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 258, + 2, 2, 2, 2, 2, 2, 259, 0, 2, 2, 260, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 261, 2, 262, 0, 0, 1, 77, 0, 0, 0, 0, 0, 0, + 243, 263, 264, 265, 266, 267, 0, 268, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 83, 2, 2, 75, 269, 270, 79, 2, 2, 2, 2, 2, 254, 0, 271, + 210, 53, 272, 241, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 166, 273, 2, 2, 2, 274, 2, 2, 69, 275, + 83, 2, 179, 2, 10, 276, 190, 0, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 75, 277, 278, 2, 279, 280, 2, 2, 2, 2, 139, 2, 2, 69, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 69, 2, 2, 2, 2, 2, 2, + 77, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 281, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 102, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 18, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 229, 0, 0, + 282, 2, 2, 2, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 229, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 77 +}; + +static RE_UINT8 re_graph_table_3[] = { + 0, 0, 0, 0, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 127, + 255, 255, 255, 252, 240, 215, 255, 255, 251, 255, 255, 255, 255, 255, 254, 255, + 255, 255, 127, 254, 255, 231, 254, 255, 255, 0, 255, 255, 255, 135, 31, 0, + 255, 191, 255, 255, 255, 231, 255, 255, 255, 255, 3, 0, 255, 255, 255, 231, + 255, 63, 255, 127, 255, 255, 255, 79, 255, 7, 255, 255, 255, 127, 131, 255, + 239, 159, 249, 255, 255, 253, 197, 243, 159, 121, 128, 176, 207, 255, 255, 127, + 238, 135, 249, 255, 255, 253, 109, 211, 135, 57, 2, 94, 192, 255, 127, 0, + 238, 191, 251, 255, 255, 253, 237, 243, 191, 59, 1, 0, 207, 255, 3, 254, + 238, 159, 249, 255, 159, 57, 224, 176, 207, 255, 255, 0, 236, 199, 61, 214, + 24, 199, 255, 195, 199, 61, 129, 0, 192, 255, 255, 7, 255, 223, 253, 255, + 255, 253, 255, 243, 223, 61, 96, 39, 207, 255, 128, 255, 255, 253, 239, 243, + 223, 61, 96, 96, 207, 255, 14, 0, 223, 253, 240, 255, 207, 255, 255, 255, + 238, 255, 127, 252, 255, 255, 251, 47, 127, 132, 95, 255, 192, 255, 28, 0, + 255, 255, 255, 135, 255, 255, 255, 15, 214, 247, 255, 255, 175, 255, 255, 63, + 95, 127, 255, 243, 255, 254, 255, 255, 255, 31, 254, 255, 255, 255, 255, 254, + 255, 255, 255, 223, 255, 223, 255, 7, 191, 32, 255, 255, 255, 61, 127, 61, + 255, 61, 255, 255, 255, 255, 61, 127, 61, 255, 127, 255, 255, 255, 61, 255, + 255, 255, 255, 31, 255, 255, 255, 3, 255, 255, 63, 63, 254, 255, 255, 31, + 255, 255, 255, 1, 255, 255, 63, 128, 255, 255, 127, 0, 255, 255, 15, 0, + 255, 223, 13, 0, 255, 255, 255, 63, 255, 3, 255, 3, 255, 255, 63, 0, + 255, 15, 255, 15, 241, 255, 255, 255, 255, 63, 31, 0, 255, 15, 255, 255, + 255, 3, 255, 199, 255, 255, 255, 207, 255, 255, 255, 159, 255, 63, 255, 255, + 255, 127, 0, 0, 255, 223, 255, 255, 255, 255, 15, 240, 255, 255, 255, 248, + 255, 227, 255, 255, 255, 255, 255, 7, 63, 63, 255, 170, 255, 255, 223, 255, + 223, 255, 207, 239, 255, 255, 220, 127, 0, 248, 255, 255, 255, 124, 255, 255, + 223, 255, 243, 255, 255, 127, 255, 31, 1, 0, 255, 255, 255, 255, 1, 0, + 255, 3, 0, 0, 255, 7, 0, 0, 255, 255, 207, 255, 255, 255, 191, 255, + 255, 255, 15, 254, 255, 128, 1, 128, 127, 127, 127, 127, 255, 255, 255, 251, + 0, 0, 255, 255, 224, 255, 255, 255, 255, 127, 255, 255, 63, 128, 255, 255, + 255, 31, 255, 255, 127, 0, 255, 255, 255, 15, 0, 0, 255, 255, 255, 0, + 255, 63, 235, 31, 0, 0, 252, 255, 255, 31, 255, 3, 63, 192, 255, 3, + 255, 255, 15, 128, 255, 191, 255, 195, 255, 63, 255, 243, 7, 0, 0, 248, + 126, 126, 126, 0, 127, 127, 255, 255, 255, 63, 255, 3, 15, 0, 255, 255, + 127, 248, 255, 255, 127, 0, 248, 224, 255, 255, 127, 95, 219, 255, 255, 255, + 7, 0, 248, 255, 255, 255, 252, 255, 255, 128, 0, 0, 255, 255, 247, 255, + 127, 15, 223, 255, 252, 252, 252, 28, 127, 127, 0, 62, 255, 239, 255, 255, + 127, 255, 255, 183, 255, 63, 255, 63, 135, 255, 255, 255, 255, 255, 143, 255, + 1, 0, 0, 0, 15, 224, 255, 255, 255, 255, 255, 191, 15, 255, 63, 0, + 255, 3, 255, 255, 255, 255, 15, 255, 15, 128, 255, 247, 255, 247, 183, 255, + 251, 255, 251, 27, 255, 0, 0, 0, 191, 255, 255, 255, 255, 255, 253, 7, + 63, 253, 255, 255, 255, 255, 191, 145, 128, 255, 0, 0, 255, 255, 55, 248, + 255, 255, 255, 143, 255, 255, 255, 131, 255, 255, 255, 240, 111, 240, 239, 254, + 255, 255, 63, 135, 255, 1, 255, 1, 127, 248, 127, 0, 255, 255, 63, 254, + 255, 255, 63, 255, 255, 255, 7, 255, 255, 255, 3, 30, 0, 254, 0, 0, + 255, 1, 0, 0, 255, 255, 7, 0, 255, 255, 7, 252, 255, 0, 255, 3, + 63, 254, 255, 255, 63, 192, 0, 0, 255, 59, 3, 0, 28, 0, 0, 0, + 0, 0, 0, 240, 255, 63, 252, 255, 7, 32, 255, 255, 255, 1, 255, 3, + 254, 255, 31, 0, 255, 255, 251, 255, 3, 0, 0, 0, 127, 189, 255, 191, + 255, 7, 255, 3, 255, 253, 237, 251, 159, 57, 129, 224, 207, 31, 31, 0, + 255, 75, 255, 255, 165, 247, 191, 1, 6, 0, 0, 0, 255, 255, 255, 239, + 31, 0, 255, 3, 255, 31, 0, 0, 15, 0, 0, 0, 127, 0, 0, 0, + 255, 255, 7, 128, 127, 242, 111, 255, 255, 255, 191, 249, 127, 0, 255, 3, + 255, 252, 255, 255, 31, 0, 0, 0, 7, 0, 255, 255, 3, 0, 255, 3, + 255, 253, 255, 255, 255, 255, 127, 255, 63, 0, 255, 255, 255, 254, 127, 0, + 127, 251, 255, 255, 255, 255, 127, 180, 191, 253, 255, 255, 255, 127, 251, 1, + 255, 255, 253, 255, 255, 255, 255, 199, 0, 0, 1, 0, 255, 255, 3, 128, + 255, 127, 31, 0, 255, 195, 255, 255, 255, 63, 63, 0, 63, 0, 255, 251, + 251, 255, 255, 224, 255, 255, 0, 0, 255, 135, 255, 255, 255, 128, 255, 255, + 31, 0, 3, 0, 0, 0, 0, 128, 0, 0, 239, 111, 7, 0, 4, 0, + 0, 0, 39, 0, 240, 0, 255, 255, 255, 7, 255, 31, 255, 1, 255, 243, + 127, 254, 255, 255, 63, 0, 0, 0, 100, 222, 255, 235, 239, 255, 255, 255, + 191, 231, 223, 223, 255, 255, 255, 123, 95, 252, 253, 255, 63, 255, 255, 255, + 255, 207, 255, 255, 255, 15, 0, 248, 254, 255, 0, 0, 224, 7, 0, 0, + 127, 255, 255, 249, 219, 7, 255, 255, 255, 63, 0, 0, 0, 128, 0, 0, + 255, 31, 255, 63, 255, 195, 0, 0, 127, 111, 255, 127, 159, 255, 127, 0, + 255, 15, 255, 195, 0, 0, 254, 255, 255, 255, 31, 0, 150, 254, 247, 10, + 132, 234, 150, 170, 150, 247, 247, 94, 255, 251, 255, 15, 238, 251, 255, 15, + 0, 0, 3, 0, 255, 127, 254, 255, 254, 255, 254, 255, 192, 255, 255, 255, + 255, 1, 3, 0, 255, 31, 255, 31, 255, 255, 127, 248, 255, 15, 1, 0, + 255, 63, 255, 15, 255, 63, 255, 31, 255, 131, 255, 255, 127, 192, 255, 159, + 255, 3, 255, 1, 3, 0, 255, 255, 2, 0, 0, 0 +}; + +RE_UINT32 re_get_graph(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_graph_table_1[field_2]; + v = re_graph_table_2[(v << 5) | field_1]; + v = re_graph_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Grapheme_Base. */ +static RE_UINT8 re_grapheme_base_table_1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 15, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 16, 17, 17, 17, 17, 17, 17, 17, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 17, 30, 13, 31, 13, 13, + 32, 33, 17, 17, 17, 17, 17, 17, 34, 17, 35, 36, 13, 13, 13, 13, + 13, 37, 13, 38, 17, 17, 17, 17, 17, 17, 17, 39, 40, 17, 17, 41, + 17, 17, 17, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 17, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 54, 13, 13, 13, 55, 56, 13, + 13, 13, 13, 57, 13, 13, 13, 13, 13, 13, 58, 59, 17, 17, 60, 17, + 13, 13, 13, 13, 61, 13, 13, 13, 62, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17 +}; + +static RE_UINT16 re_grapheme_base_table_2[] = { + 0, 1, 1, 2, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 4, 5, 6, 1, 1, + 1, 1, 1, 1, 7, 1, 1, 1, 1, 8, 9, 1, 10, 11, 12, 13, + 14, 1, 15, 8, 1, 1, 16, 17, 18, 19, 20, 1, 1, 21, 1, 22, + 23, 24, 25, 26, 27, 1, 28, 0, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, + 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + 69, 70, 71, 0, 72, 73, 74, 0, 75, 76, 77, 78, 79, 80, 81, 0, + 1, 82, 83, 84, 85, 1, 86, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 87, 1, 88, 89, 90, 1, 91, 1, 92, 93, 94, 1, 1, 95, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 93, 1, 1, 96, 97, 98, 99, 100, 1, 101, 102, 103, + 104, 1, 1, 96, 105, 106, 1, 107, 2, 108, 109, 110, 1, 111, 112, 1, + 113, 1, 114, 115, 103, 116, 0, 0, 117, 118, 119, 120, 121, 122, 1, 123, + 1, 124, 125, 1, 26, 126, 127, 128, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 95, 1, 129, 130, 1, 131, 132, 133, + 26, 134, 1, 135, 136, 1, 137, 0, 1, 1, 1, 1, 111, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 28, 15, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 138, 139, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 140, 1, 86, 1, 141, 142, 143, 143, 0, + 1, 1, 130, 0, 144, 1, 1, 145, 1, 1, 1, 1, 1, 1, 107, 146, + 1, 147, 69, 1, 148, 1, 1, 1, 149, 8, 1, 1, 150, 1, 1, 151, + 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 152, 1, 153, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 154, 1, 155, 130, 1, 1, 156, 1, 1, 1, 1, 1, 1, 157, 158, + 159, 160, 1, 161, 1, 1, 162, 163, 1, 164, 165, 93, 29, 166, 167, 168, + 1, 169, 170, 171, 1, 172, 173, 174, 175, 176, 1, 111, 1, 1, 1, 177, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 178, 179, 180, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 181, 1, 1, 94, 0, 182, 183, 184, 1, 1, 1, 185, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 186, 1, 187, 146, + 188, 146, 189, 190, 1, 1, 1, 93, 69, 1, 1, 1, 130, 2, 191, 192, + 193, 194, 195, 0, 1, 1, 1, 92, 196, 197, 1, 1, 136, 137, 146, 93, + 0, 0, 0, 0, 93, 1, 198, 199, 1, 200, 26, 107, 201, 1, 202, 0, + 1, 1, 1, 1, 130, 147, 203, 180, 1, 204, 1, 205, 206, 207, 1, 145, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 142, 107, 208, 209, 210, 0, 0, + 211, 212, 139, 1, 2, 213, 0, 214, 215, 216, 0, 0, 1, 217, 186, 1, + 218, 107, 219, 1, 1, 0, 1, 220, 1, 221, 222, 223, 224, 225, 0, 0, + 1, 1, 226, 0, 1, 227, 1, 228, 1, 229, 1, 164, 230, 0, 0, 0, + 0, 0, 0, 2, 1, 231, 232, 0, 1, 204, 233, 146, 234, 146, 154, 142, + 235, 161, 236, 237, 121, 238, 239, 240, 29, 241, 204, 242, 121, 243, 244, 245, + 246, 247, 137, 0, 248, 147, 2, 249, 45, 250, 251, 252, 253, 254, 255, 0, + 1, 161, 256, 257, 1, 258, 259, 0, 0, 0, 0, 0, 1, 260, 199, 0, + 1, 261, 262, 263, 1, 264, 147, 252, 265, 266, 267, 0, 0, 0, 0, 0, + 1, 268, 0, 0, 0, 1, 1, 269, 270, 271, 272, 0, 0, 273, 274, 275, + 276, 277, 278, 1, 279, 280, 1, 96, 28, 0, 0, 0, 0, 0, 1, 281, + 282, 283, 284, 152, 19, 285, 0, 0, 286, 198, 287, 288, 289, 28, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 290, 291, 292, 293, 0, 0, 294, 1, 97, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 94, 0, 0, 0, + 1, 1, 1, 295, 1, 1, 1, 1, 1, 1, 252, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146, 1, 1, 227, + 1, 19, 296, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 92, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 267, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 130, 297, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 96, 2, 298, 1, 2, 147, 299, 1, 300, 301, 302, 19, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 94, 0, 0, 0, 0, + 0, 0, 1, 1, 92, 0, 0, 0, 1, 1, 26, 1, 303, 0, 0, 252, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 161, + 1, 1, 1, 1, 1, 1, 107, 304, 226, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 305, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 306, 307, 308, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 180, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 309, 310, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 94, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 145, 0, 0, 0, 0, 146, 1, 1, 1, 252, 0, + 1, 1, 1, 1, 1, 1, 1, 107, 1, 311, 1, 312, 313, 298, 1, 15, + 1, 1, 314, 0, 0, 0, 145, 145, 1, 1, 142, 96, 0, 0, 0, 0, + 1, 1, 131, 1, 315, 316, 317, 1, 318, 319, 320, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 321, 1, 1, 1, 1, 1, 1, 1, 1, 322, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 323, 0, 324, 325, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2, 326, 0, 0, 0, 0, 0, 0, + 0, 146, 1, 116, 0, 0, 0, 0, 1, 327, 328, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 146, 116, 1, 329, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 146, 330, 0, 0, 0, 0, 0, 0, 146, 331, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 332, + 1, 1, 1, 1, 1, 1, 333, 0, 1, 1, 334, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 335, 1, 336, 0, 0, 69, 130, 0, 0, 0, 0, 0, 0, + 317, 337, 338, 339, 340, 341, 0, 342, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 111, 1, 1, 145, 343, 344, 107, 1, 1, 1, 1, 1, 116, 0, 345, + 280, 180, 346, 347, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 217, 348, 1, 1, 1, 148, 1, 1, 94, 349, + 111, 1, 350, 1, 204, 351, 257, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 145, 352, 353, 1, 354, 355, 1, 1, 1, 1, 189, 1, 1, 94, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 94, 1, 1, 1, 1, 1, 1, + 130, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 239, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 356, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 26, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 0, 0 +}; + +static RE_UINT8 re_grapheme_base_table_3[] = { + 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 127, 255, 223, 255, 255, + 0, 0, 255, 252, 240, 215, 255, 255, 251, 255, 255, 255, 7, 252, 255, 255, + 255, 255, 254, 255, 255, 255, 127, 254, 255, 231, 0, 0, 0, 0, 0, 64, + 73, 0, 255, 255, 255, 135, 31, 0, 192, 255, 0, 232, 255, 7, 0, 0, + 255, 255, 63, 64, 96, 194, 255, 255, 255, 63, 253, 255, 255, 255, 0, 0, + 0, 224, 255, 255, 63, 0, 2, 0, 255, 7, 240, 199, 255, 255, 63, 4, + 16, 1, 255, 127, 255, 255, 255, 65, 255, 7, 255, 255, 255, 127, 0, 0, + 255, 3, 0, 0, 248, 255, 255, 255, 255, 255, 255, 235, 1, 222, 1, 255, + 243, 255, 255, 255, 237, 159, 249, 255, 255, 253, 197, 163, 129, 89, 0, 176, + 195, 255, 255, 63, 232, 135, 249, 255, 255, 253, 109, 195, 1, 0, 0, 94, + 192, 255, 92, 0, 232, 191, 251, 255, 255, 253, 237, 227, 1, 26, 1, 0, + 195, 255, 3, 2, 236, 159, 249, 255, 255, 253, 237, 35, 129, 25, 0, 176, + 195, 255, 255, 0, 232, 199, 61, 214, 24, 199, 255, 131, 198, 29, 1, 0, + 192, 255, 255, 7, 238, 223, 253, 255, 255, 253, 255, 35, 30, 0, 0, 39, + 195, 255, 128, 255, 253, 223, 253, 255, 255, 253, 239, 99, 26, 0, 0, 96, + 195, 255, 14, 0, 252, 223, 253, 255, 255, 255, 255, 167, 193, 221, 112, 255, + 195, 255, 255, 255, 236, 255, 127, 252, 255, 255, 251, 47, 127, 0, 3, 127, + 192, 255, 28, 0, 254, 255, 255, 255, 255, 255, 13, 128, 127, 128, 255, 15, + 214, 247, 255, 255, 175, 255, 13, 32, 95, 0, 255, 243, 255, 255, 255, 252, + 255, 255, 95, 253, 255, 254, 255, 255, 255, 31, 0, 128, 32, 31, 0, 0, + 0, 0, 0, 192, 191, 223, 255, 7, 255, 31, 2, 153, 255, 255, 255, 60, + 254, 255, 225, 255, 155, 223, 255, 223, 191, 32, 255, 255, 255, 61, 127, 61, + 255, 61, 255, 255, 255, 255, 61, 127, 61, 255, 127, 255, 255, 255, 61, 255, + 255, 255, 255, 7, 255, 255, 255, 31, 255, 255, 255, 3, 255, 255, 63, 63, + 255, 255, 255, 1, 255, 255, 3, 128, 255, 255, 99, 0, 255, 255, 3, 0, + 255, 223, 1, 0, 255, 255, 79, 192, 191, 1, 240, 31, 255, 3, 255, 3, + 255, 7, 255, 3, 159, 255, 255, 255, 255, 5, 255, 255, 255, 255, 63, 0, + 120, 14, 251, 1, 241, 255, 255, 255, 255, 63, 31, 0, 255, 15, 255, 255, + 255, 3, 255, 199, 255, 255, 127, 198, 255, 255, 191, 0, 26, 224, 7, 0, + 255, 63, 0, 0, 240, 255, 255, 255, 255, 255, 15, 192, 227, 223, 255, 255, + 255, 7, 240, 255, 252, 255, 255, 255, 195, 192, 255, 255, 191, 92, 0, 240, + 255, 15, 48, 248, 255, 227, 255, 255, 255, 255, 255, 231, 255, 0, 8, 0, + 2, 222, 239, 4, 63, 63, 255, 170, 255, 255, 255, 63, 255, 255, 223, 255, + 223, 255, 207, 239, 255, 255, 220, 127, 255, 128, 255, 255, 0, 0, 243, 255, + 255, 127, 255, 31, 1, 0, 0, 0, 255, 255, 207, 255, 255, 255, 191, 255, + 255, 127, 12, 254, 255, 128, 1, 0, 255, 255, 127, 0, 127, 127, 127, 127, + 255, 255, 255, 251, 255, 255, 15, 0, 0, 0, 255, 255, 255, 3, 255, 255, + 255, 255, 127, 248, 224, 255, 255, 255, 255, 127, 255, 255, 63, 128, 255, 255, + 255, 31, 255, 255, 127, 0, 255, 255, 255, 15, 0, 0, 255, 127, 8, 192, + 255, 255, 252, 0, 255, 63, 235, 31, 0, 0, 252, 255, 187, 247, 255, 255, + 159, 15, 255, 3, 255, 255, 255, 0, 15, 192, 255, 3, 0, 0, 252, 127, + 63, 192, 255, 255, 127, 0, 4, 128, 255, 255, 55, 204, 254, 191, 255, 195, + 223, 255, 255, 127, 255, 129, 25, 0, 247, 47, 255, 243, 255, 255, 255, 239, + 255, 255, 98, 62, 5, 0, 0, 248, 255, 207, 63, 0, 126, 126, 126, 0, + 127, 127, 255, 255, 223, 30, 255, 3, 15, 0, 255, 255, 127, 248, 255, 255, + 255, 255, 255, 15, 255, 63, 255, 255, 127, 0, 248, 160, 255, 255, 127, 95, + 219, 255, 255, 255, 7, 0, 248, 255, 255, 255, 252, 255, 255, 128, 0, 0, + 0, 0, 255, 3, 255, 255, 247, 255, 127, 15, 223, 255, 252, 252, 252, 28, + 127, 127, 0, 48, 255, 239, 255, 255, 127, 255, 255, 183, 255, 63, 255, 63, + 135, 255, 255, 255, 255, 255, 143, 255, 255, 255, 1, 0, 254, 255, 255, 15, + 15, 224, 255, 255, 255, 255, 255, 191, 15, 255, 63, 0, 255, 255, 15, 255, + 255, 0, 255, 255, 15, 128, 255, 247, 255, 247, 183, 255, 251, 255, 251, 27, + 255, 0, 0, 0, 191, 255, 255, 255, 255, 255, 253, 7, 63, 253, 255, 255, + 255, 255, 191, 145, 128, 255, 0, 0, 255, 255, 55, 248, 255, 255, 255, 143, + 255, 255, 255, 131, 255, 255, 255, 240, 1, 0, 239, 254, 255, 1, 255, 1, + 31, 248, 127, 0, 255, 255, 63, 254, 255, 255, 63, 255, 255, 255, 7, 255, + 255, 255, 3, 30, 0, 254, 0, 0, 255, 1, 0, 0, 255, 255, 7, 0, + 255, 255, 7, 252, 15, 0, 255, 3, 63, 192, 0, 0, 255, 35, 3, 0, + 28, 0, 0, 0, 63, 0, 254, 3, 195, 3, 0, 0, 253, 255, 255, 255, + 128, 63, 252, 255, 255, 255, 38, 0, 255, 255, 135, 217, 3, 0, 255, 255, + 255, 1, 255, 3, 127, 16, 192, 255, 255, 255, 119, 0, 255, 255, 63, 128, + 254, 97, 255, 255, 254, 255, 31, 0, 255, 255, 251, 255, 255, 127, 12, 191, + 127, 189, 255, 191, 7, 0, 255, 3, 255, 253, 237, 163, 158, 25, 1, 224, + 15, 0, 0, 0, 255, 75, 255, 255, 255, 255, 191, 6, 0, 52, 186, 1, + 163, 255, 255, 175, 3, 0, 0, 0, 255, 255, 6, 90, 242, 0, 255, 3, + 255, 127, 3, 79, 255, 255, 7, 88, 30, 0, 255, 3, 255, 31, 0, 0, + 255, 215, 0, 3, 255, 255, 255, 71, 67, 0, 255, 255, 127, 0, 0, 0, + 255, 127, 0, 9, 255, 255, 7, 128, 127, 242, 111, 255, 255, 255, 190, 129, + 119, 0, 255, 3, 255, 252, 255, 255, 255, 255, 15, 240, 30, 0, 0, 0, + 1, 248, 255, 255, 255, 255, 7, 134, 127, 0, 129, 241, 255, 3, 128, 252, + 7, 0, 255, 255, 3, 0, 255, 3, 255, 253, 255, 255, 255, 255, 0, 64, + 63, 0, 255, 255, 0, 2, 18, 0, 127, 251, 255, 255, 64, 0, 255, 3, + 191, 253, 255, 255, 255, 127, 88, 1, 255, 255, 231, 1, 252, 255, 253, 255, + 255, 255, 63, 192, 248, 255, 255, 3, 0, 0, 1, 0, 255, 127, 31, 0, + 126, 0, 0, 0, 0, 28, 255, 3, 255, 195, 255, 255, 255, 63, 32, 0, + 255, 255, 128, 255, 63, 0, 255, 251, 251, 255, 255, 224, 255, 0, 248, 255, + 0, 0, 0, 128, 0, 0, 239, 111, 7, 0, 4, 0, 0, 0, 39, 0, + 240, 0, 255, 255, 255, 7, 255, 31, 255, 1, 255, 147, 127, 254, 255, 255, + 31, 28, 0, 0, 24, 240, 255, 255, 35, 0, 0, 0, 255, 255, 255, 223, + 100, 222, 255, 235, 239, 255, 255, 255, 191, 231, 223, 223, 255, 255, 255, 123, + 95, 252, 253, 255, 63, 255, 255, 255, 255, 207, 255, 255, 0, 0, 128, 7, + 0, 224, 223, 255, 239, 15, 0, 0, 224, 7, 0, 0, 255, 31, 128, 63, + 255, 195, 0, 0, 255, 15, 255, 131, 255, 15, 255, 3, 255, 63, 255, 135, + 127, 111, 255, 127, 159, 255, 0, 0, 15, 8, 255, 195, 0, 0, 254, 255, + 255, 255, 31, 0, 150, 254, 247, 10, 132, 234, 150, 170, 150, 247, 247, 94, + 255, 251, 255, 15, 238, 251, 255, 15, 0, 0, 3, 0, 255, 127, 254, 255, + 254, 255, 254, 255, 192, 255, 255, 255, 255, 1, 3, 0, 63, 0, 0, 0, + 255, 31, 255, 31, 255, 15, 1, 0, 255, 0, 255, 3, 255, 63, 255, 15, + 255, 63, 255, 31, 255, 131, 255, 255, 127, 192, 255, 159, 255, 3, 255, 1, + 1, 0, 255, 255 +}; + +RE_UINT32 re_get_grapheme_base(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_grapheme_base_table_1[field_2]; + v = re_grapheme_base_table_2[(v << 5) | field_1]; + v = re_grapheme_base_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Grapheme_Cluster_Break. */ +static RE_UINT8 re_grapheme_cluster_break_table_1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 11, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 14, 15, 16, 21, 9, 9, 9, 9, 9, 9, 9, 9, 22, 23, + 24, 9, 25, 26, 27, 28, 29, 30, 9, 9, 9, 9, 9, 31, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 32, 9, 33, 34, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 35, + 9, 9, 9, 36, 37, 9, 38, 9, 39, 40, 41, 9, 42, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 43, 44, 44, 44, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 +}; + +static RE_UINT8 re_grapheme_cluster_break_table_2[] = { + 0, 1, 1, 2, 3, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 6, 1, 1, 1, 1, + 1, 1, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 8, 9, 10, 1, + 11, 1, 12, 13, 1, 1, 14, 15, 16, 17, 18, 1, 1, 19, 1, 20, + 21, 22, 23, 1, 24, 1, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 35, 36, 39, 40, 31, 41, 42, 30, 43, 44, 45, 1, + 46, 41, 47, 30, 31, 48, 49, 50, 51, 52, 53, 30, 31, 1, 54, 55, + 1, 56, 57, 1, 1, 58, 59, 1, 60, 61, 1, 62, 63, 64, 65, 1, + 1, 66, 67, 68, 69, 1, 1, 1, 70, 70, 70, 71, 71, 72, 73, 73, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 74, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 75, 76, 77, 77, 1, 78, 79, 1, + 80, 1, 1, 1, 81, 82, 1, 1, 1, 83, 1, 1, 1, 1, 1, 1, + 84, 1, 85, 86, 1, 17, 87, 1, 88, 89, 90, 91, 92, 93, 1, 94, + 1, 95, 1, 1, 1, 1, 96, 97, 1, 1, 1, 1, 1, 1, 5, 5, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 98, 99, 1, 100, 1, 1, 17, 101, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 102, 1, 1, 1, 103, 1, 1, 1, 5, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 104, 1, 1, 105, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 106, 107, 1, 1, 108, 1, 1, 1, 1, 1, 1, 1, 1, + 109, 110, 1, 1, 111, 112, 113, 114, 1, 115, 116, 117, 27, 118, 119, 120, + 1, 121, 122, 123, 1, 124, 125, 126, 1, 1, 1, 1, 1, 1, 1, 127, + 128, 129, 130, 131, 132, 133, 134, 128, 129, 130, 131, 132, 133, 134, 128, 129, + 130, 131, 132, 133, 134, 128, 129, 130, 131, 132, 133, 134, 128, 129, 130, 131, + 132, 133, 134, 128, 129, 130, 131, 132, 133, 134, 128, 129, 130, 131, 132, 133, + 134, 128, 129, 130, 131, 132, 133, 134, 128, 129, 130, 131, 132, 133, 134, 128, + 129, 130, 131, 132, 133, 134, 128, 129, 130, 131, 132, 133, 134, 128, 129, 130, + 131, 132, 133, 134, 128, 129, 130, 131, 132, 133, 134, 128, 129, 130, 131, 132, + 133, 134, 128, 129, 130, 131, 132, 133, 134, 128, 129, 130, 131, 132, 133, 134, + 128, 129, 130, 131, 132, 133, 134, 128, 129, 130, 131, 132, 133, 134, 128, 129, + 130, 131, 132, 133, 134, 128, 129, 130, 131, 132, 133, 134, 128, 129, 130, 131, + 132, 133, 134, 128, 129, 130, 131, 132, 133, 134, 128, 129, 130, 131, 132, 133, + 134, 128, 129, 130, 131, 132, 133, 134, 128, 129, 130, 131, 132, 133, 134, 128, + 129, 130, 131, 132, 133, 134, 128, 129, 130, 131, 132, 133, 134, 128, 129, 130, + 131, 132, 133, 134, 128, 129, 130, 131, 132, 133, 134, 128, 129, 130, 131, 132, + 133, 134, 128, 129, 130, 131, 132, 133, 134, 128, 129, 130, 131, 132, 133, 134, + 133, 134, 128, 129, 130, 131, 132, 133, 134, 128, 129, 130, 131, 132, 133, 134, + 128, 129, 130, 131, 132, 133, 134, 128, 129, 130, 131, 132, 133, 135, 136, 137, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 138, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 6, 6, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 107, 1, 1, 139, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 140, + 1, 1, 1, 1, 1, 1, 1, 119, 1, 1, 1, 141, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 142, 143, 1, 1, 1, 1, 1, 81, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 144, 1, 145, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 146, 1, 147, 1, 1, 19, 1, 148, 1, 1, 1, + 149, 150, 151, 152, 92, 153, 154, 1, 155, 156, 157, 158, 92, 159, 160, 1, + 1, 161, 125, 1, 1, 1, 103, 162, 51, 52, 163, 164, 1, 165, 166, 167, + 1, 168, 169, 1, 1, 170, 171, 1, 1, 1, 1, 1, 1, 172, 173, 1, + 1, 174, 119, 1, 1, 175, 1, 1, 176, 177, 1, 1, 1, 1, 1, 1, + 1, 178, 1, 1, 1, 1, 1, 1, 1, 179, 180, 1, 1, 1, 181, 182, + 183, 184, 185, 1, 186, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 187, 1, 1, 188, 189, 1, 1, 1, 190, 191, 1, 192, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 193, 194, 195, 196, 1, 1, 1, 1, 1, + 1, 197, 198, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 107, 199, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 200, 1, 201, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 202, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 203, 204, 205, 1, 1, 206, + 1, 1, 1, 1, 207, 208, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 5, 209, 151, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 210, 211, 212, 1, 1, + 1, 1, 213, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 5, 214, 5, 215, 216, 217, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 218, 219, 1, 1, 220, 1, 1, 1, 1, 201, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 221, 1, 222, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 222, 1, 1, 1, 1, 1, 1, 1, 223, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 201, 1, 1, 1, 224, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 225, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 226, + 3, 5, 5, 5, 3, 3, 3, 3, 5, 5, 5, 5, 5, 5, 5, 227, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 +}; + +static RE_UINT8 re_grapheme_cluster_break_table_3[] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 3, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, + 0, 4, 4, 0, 4, 4, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 5, 0, 4, + 4, 4, 4, 4, 4, 0, 0, 4, 4, 0, 4, 4, 4, 4, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, + 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 0, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 0, 4, 4, 4, 0, 4, 4, 4, 4, 4, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 6, 4, 0, 6, 6, + 6, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 6, 4, 6, 6, + 0, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 4, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 4, 6, + 6, 4, 4, 4, 4, 0, 0, 6, 6, 0, 0, 6, 6, 4, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, + 0, 4, 4, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 6, 6, + 6, 4, 4, 0, 0, 0, 0, 4, 4, 0, 0, 4, 4, 4, 0, 0, + 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 4, 4, 4, 4, 4, 0, 4, 4, 6, 0, 6, 6, 4, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 4, 4, + 6, 4, 4, 4, 4, 0, 0, 6, 6, 0, 0, 6, 6, 4, 0, 0, + 0, 0, 0, 0, 0, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 6, + 4, 6, 6, 0, 0, 0, 6, 6, 6, 0, 6, 6, 6, 4, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 6, 6, 6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 6, 6, 6, 6, 0, 4, 4, 4, 0, 4, 4, 4, 4, 0, 0, + 0, 0, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 6, 4, + 4, 6, 4, 6, 6, 0, 4, 4, 4, 0, 4, 4, 4, 4, 0, 0, + 0, 0, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 4, 6, + 6, 4, 4, 4, 4, 0, 6, 6, 6, 0, 6, 6, 6, 4, 5, 0, + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 4, + 6, 6, 4, 4, 4, 0, 4, 0, 6, 6, 6, 6, 6, 6, 6, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 4, 0, 6, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 4, 0, 6, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 4, 0, 4, 0, 4, 0, 0, 0, 0, 6, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, + 4, 4, 4, 4, 4, 0, 4, 4, 0, 0, 0, 0, 0, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, + 4, 6, 4, 4, 4, 4, 4, 4, 0, 4, 4, 6, 6, 4, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 6, 6, 4, 4, 0, 0, 0, 0, 4, 4, + 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 6, 4, 4, 0, 0, 0, 0, 0, 0, 4, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 4, 6, 4, 4, 4, 4, 4, 4, 4, 6, 6, + 6, 6, 6, 6, 6, 6, 4, 6, 6, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 1, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 6, 6, 6, 6, 4, 4, 6, 6, 6, 0, 0, 0, 0, + 6, 6, 4, 6, 6, 6, 6, 6, 6, 4, 4, 4, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 4, 4, 6, 6, 4, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 6, 4, 6, 4, 4, 4, 4, 4, 4, 4, 0, + 4, 0, 4, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, + 6, 6, 6, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, + 6, 6, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6, 4, 4, 4, 4, 6, 6, 4, 4, 4, 4, 4, 4, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 4, 6, 4, 4, 6, 6, 6, 4, 6, 4, + 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, 6, 4, 4, 4, 4, + 4, 4, 4, 4, 6, 6, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 6, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 4, 0, 0, + 0, 0, 0, 0, 4, 0, 0, 6, 4, 4, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 10, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, + 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, + 4, 4, 4, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 4, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 6, 6, 4, 4, 6, 0, 0, 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, + 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 4, 6, 6, 4, 4, 4, 4, 6, 6, 4, 4, 6, 6, + 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 6, + 6, 4, 4, 6, 6, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 4, 6, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 4, 4, 4, 0, 0, 4, 4, 0, 0, 0, 0, 0, 4, 4, + 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 4, 4, 6, 6, + 0, 0, 0, 0, 0, 6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 6, 6, 4, 6, 6, 4, 6, 6, 0, 6, 4, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 11, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 11, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, + 0, 4, 4, 4, 0, 4, 4, 0, 0, 0, 0, 0, 4, 4, 4, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 0, 0, 0, 0, 4, + 0, 0, 0, 0, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, + 0, 0, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 4, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 6, 6, 4, 4, 4, 4, 6, 6, 4, 4, 0, 0, 5, 0, 0, + 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 6, 4, 4, 4, + 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 6, 6, 6, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, + 4, 0, 5, 5, 0, 0, 0, 0, 0, 4, 4, 4, 4, 0, 6, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 4, + 4, 4, 6, 6, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 4, 0, + 6, 6, 6, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 6, 6, 6, 6, 0, 0, 6, 6, 0, 0, 6, 6, 4, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 6, 6, 0, 0, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, + 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 4, 6, 6, 4, 4, 4, 4, 4, + 4, 0, 4, 0, 0, 4, 0, 4, 4, 4, 6, 0, 6, 6, 4, 4, + 4, 5, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 6, 6, 6, 4, 4, 4, 4, 4, 4, 4, 4, + 6, 6, 4, 4, 4, 6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 6, 6, 4, 4, 4, 4, 4, 4, 6, 4, 6, 6, 4, 6, 4, + 4, 6, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, + 6, 6, 4, 4, 4, 4, 0, 0, 6, 6, 6, 6, 4, 4, 6, 4, + 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 6, 6, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 4, 6, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 6, 4, 6, 6, + 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 6, 4, + 0, 0, 4, 4, 4, 4, 6, 4, 4, 4, 4, 4, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 6, 4, 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 6, 6, 6, 6, 6, 0, 6, 6, 0, 0, 4, 4, 4, 4, 5, + 6, 5, 6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6, 6, 6, 4, 4, 4, 4, 0, 0, 4, 4, 6, 6, 6, 6, + 4, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 4, 4, 4, 4, 4, 4, 6, 5, 4, 4, 4, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 4, 4, 4, 4, 4, 4, 6, 6, 4, 4, 4, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 6, 4, 4, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, + 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4, 4, 4, 6, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 0, 6, 4, 4, 4, 4, 4, 4, + 4, 6, 4, 4, 6, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 4, 4, 4, 4, 4, 4, 0, 0, 0, 4, 0, 4, 4, 0, 4, + 4, 4, 4, 4, 4, 4, 5, 4, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 0, + 4, 4, 0, 6, 6, 4, 6, 4, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 4, 4, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 6, 4, 4, 4, 4, 4, 0, 0, 0, 6, 6, + 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 4, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 4, 4, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 8, 0, 0, 0, 8, 8, 8, 8, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, + 0, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 4, + 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 0, 0, 0, 4, 4, 4, + 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 4, 4, 4, + 4, 4, 4, 0, 0, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, + 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 4, 4, 4, 4, 4, + 4, 4, 0, 4, 4, 0, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +}; + +RE_UINT32 re_get_grapheme_cluster_break(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = codepoint & 0x1F; + + v = re_grapheme_cluster_break_table_1[field_2]; + v = re_grapheme_cluster_break_table_2[(v << 5) | field_1]; + v = re_grapheme_cluster_break_table_3[(v << 5) | field_0]; + + return v; +} + +/* Grapheme_Extend. */ +static RE_UINT8 re_grapheme_extend_table_1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 11, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 12, 13, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 14, 15, + 16, 9, 17, 18, 19, 20, 21, 22, 9, 9, 9, 9, 9, 23, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 24, 9, 25, 26, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 27, + 9, 9, 9, 28, 29, 9, 30, 9, 31, 32, 33, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 34, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 +}; + +static RE_UINT8 re_grapheme_extend_table_2[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 5, 6, 0, + 7, 0, 8, 9, 0, 0, 10, 11, 12, 13, 14, 0, 0, 15, 0, 16, + 17, 18, 19, 0, 20, 0, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32, 33, 34, 31, 32, 35, 36, 27, 37, 38, 26, 39, 40, 41, 0, + 42, 37, 43, 26, 27, 44, 45, 26, 46, 47, 29, 26, 27, 0, 48, 0, + 0, 49, 50, 0, 0, 51, 52, 0, 53, 54, 0, 55, 56, 57, 58, 0, + 0, 59, 60, 61, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 64, 65, 66, 66, 0, 67, 68, 0, + 69, 0, 0, 0, 70, 71, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, + 73, 0, 74, 75, 0, 13, 76, 0, 77, 78, 79, 80, 46, 81, 0, 82, + 0, 83, 0, 0, 0, 0, 84, 85, 0, 0, 0, 0, 0, 0, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 86, 0, 0, 0, 0, 0, 13, 87, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 88, 0, 0, 0, 89, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 90, 0, 0, 91, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 92, 93, 0, 0, 94, 0, 0, 0, 0, 0, 0, 0, 0, + 95, 96, 0, 0, 0, 0, 97, 98, 0, 99, 100, 0, 23, 101, 102, 103, + 0, 104, 105, 32, 0, 106, 27, 107, 0, 0, 0, 0, 0, 0, 0, 108, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, + 0, 0, 0, 0, 0, 0, 0, 102, 0, 0, 0, 110, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 111, 112, 0, 0, 0, 0, 0, 70, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 113, 0, 114, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 115, 0, 116, 0, 0, 15, 0, 117, 0, 0, 0, + 27, 118, 119, 120, 46, 121, 39, 0, 23, 122, 0, 123, 46, 124, 125, 0, + 0, 126, 27, 0, 0, 0, 89, 127, 46, 47, 41, 128, 0, 129, 130, 31, + 0, 118, 131, 0, 0, 132, 133, 0, 0, 0, 0, 0, 0, 134, 135, 0, + 0, 136, 102, 0, 0, 137, 0, 0, 138, 139, 0, 0, 0, 0, 0, 0, + 0, 140, 0, 0, 0, 0, 0, 0, 0, 141, 142, 0, 0, 0, 143, 102, + 144, 145, 146, 0, 147, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 148, 0, 0, 149, 150, 0, 0, 0, 151, 152, 0, 153, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 154, 46, 110, 155, 0, 0, 0, 0, 0, + 0, 0, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 93, 157, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 158, 0, 159, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160, 0, 161, 0, 0, 162, + 0, 0, 0, 0, 163, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 164, 119, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 166, 167, 0, 0, + 0, 0, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 168, 1, 169, 170, 171, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 172, 173, 0, 0, 160, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 174, 0, 175, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 175, 0, 0, 0, 0, 0, 0, 0, 176, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 177, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_grapheme_extend_table_3[] = { + 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 0, 248, 3, 0, 0, + 0, 0, 254, 255, 255, 255, 255, 191, 182, 0, 0, 0, 0, 0, 255, 7, + 0, 248, 255, 255, 0, 0, 1, 0, 0, 0, 192, 159, 159, 61, 0, 0, + 0, 0, 2, 0, 0, 0, 255, 255, 255, 7, 0, 0, 192, 255, 1, 0, + 0, 248, 15, 32, 0, 0, 192, 251, 239, 62, 0, 0, 0, 0, 0, 14, + 0, 0, 128, 255, 0, 252, 255, 255, 251, 255, 255, 255, 7, 0, 0, 0, + 0, 0, 0, 20, 254, 33, 254, 0, 12, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 0, 80, 30, 32, 128, 0, 12, 0, 0, 64, 6, 0, 0, 0, + 0, 0, 0, 16, 134, 57, 2, 0, 0, 0, 35, 0, 190, 33, 0, 0, + 12, 0, 0, 252, 0, 0, 0, 208, 30, 32, 224, 0, 4, 0, 0, 0, + 0, 0, 0, 64, 1, 32, 128, 0, 17, 0, 0, 0, 193, 61, 96, 0, + 0, 0, 0, 144, 197, 61, 96, 0, 3, 0, 0, 0, 0, 0, 0, 88, + 0, 132, 92, 128, 0, 0, 242, 7, 128, 127, 0, 0, 0, 0, 242, 31, + 0, 127, 0, 0, 0, 0, 0, 3, 0, 0, 160, 2, 0, 0, 254, 127, + 223, 224, 255, 254, 255, 255, 255, 31, 64, 0, 0, 0, 0, 224, 253, 102, + 0, 0, 0, 195, 1, 0, 30, 0, 100, 32, 0, 32, 0, 0, 0, 224, + 0, 0, 60, 0, 0, 0, 28, 0, 0, 0, 12, 0, 0, 0, 176, 63, + 64, 254, 15, 32, 0, 184, 0, 0, 96, 0, 0, 0, 0, 2, 0, 0, + 135, 1, 4, 14, 0, 0, 128, 9, 0, 0, 64, 127, 229, 31, 248, 159, + 255, 127, 0, 0, 15, 0, 0, 0, 0, 0, 240, 63, 28, 0, 0, 0, + 0, 248, 15, 0, 60, 63, 0, 0, 64, 163, 15, 0, 0, 240, 207, 0, + 0, 0, 247, 255, 253, 33, 16, 3, 0, 16, 0, 0, 255, 255, 1, 0, + 0, 128, 3, 0, 0, 0, 0, 128, 0, 252, 0, 0, 0, 0, 0, 6, + 0, 128, 247, 63, 0, 0, 0, 192, 0, 0, 3, 0, 68, 8, 0, 0, + 96, 16, 0, 0, 48, 0, 0, 0, 255, 255, 3, 128, 192, 63, 0, 0, + 128, 255, 11, 0, 0, 0, 200, 51, 1, 0, 0, 0, 32, 0, 0, 0, + 0, 126, 102, 0, 8, 16, 0, 0, 0, 0, 157, 193, 0, 48, 64, 0, + 32, 33, 0, 0, 0, 0, 0, 32, 0, 0, 192, 7, 110, 240, 0, 0, + 0, 0, 0, 135, 240, 0, 0, 0, 0, 62, 0, 0, 0, 24, 0, 0, + 0, 0, 0, 240, 60, 0, 0, 0, 0, 0, 0, 255, 127, 0, 0, 0, + 0, 0, 25, 128, 0, 0, 120, 6, 128, 239, 31, 0, 0, 0, 8, 0, + 0, 0, 192, 127, 1, 158, 0, 0, 0, 128, 243, 64, 248, 7, 0, 0, + 192, 31, 31, 0, 0, 0, 0, 249, 165, 195, 5, 0, 92, 0, 0, 64, + 0, 0, 249, 165, 13, 0, 0, 0, 0, 128, 60, 176, 1, 0, 0, 48, + 0, 0, 248, 167, 0, 40, 255, 0, 0, 0, 0, 160, 188, 15, 0, 0, + 0, 128, 255, 6, 0, 0, 1, 120, 8, 0, 0, 0, 0, 0, 240, 12, + 254, 7, 0, 0, 0, 0, 248, 121, 128, 0, 126, 14, 0, 252, 127, 3, + 0, 0, 127, 191, 0, 0, 252, 255, 255, 252, 109, 0, 0, 0, 126, 180, + 191, 0, 0, 0, 0, 0, 163, 0, 0, 0, 24, 0, 7, 0, 0, 4, + 129, 255, 63, 0, 255, 227, 0, 0, 0, 0, 31, 0, 0, 0, 127, 0, + 0, 128, 0, 0, 0, 128, 7, 0, 16, 0, 3, 0, 0, 0, 0, 96, + 255, 63, 255, 255, 224, 227, 7, 248, 231, 15, 0, 0, 0, 60, 0, 0, + 255, 255, 127, 248, 255, 31, 32, 0, 16, 0, 0, 248, 254, 255, 0, 0, + 127, 255, 255, 249, 219, 7, 0, 0, 0, 64, 0, 0, 0, 240, 0, 0, + 0, 192, 0, 0, 240, 7, 0, 0 +}; + +RE_UINT32 re_get_grapheme_extend(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_grapheme_extend_table_1[field_2]; + v = re_grapheme_extend_table_2[(v << 5) | field_1]; + v = re_grapheme_extend_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Grapheme_Link. */ +static RE_UINT8 re_grapheme_link_table_1[] = { + 0, 0, 1, 2, 3, 4, 5, 0, 0, 0, 0, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 9, 10, 11, 12, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_grapheme_link_table_2[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, 1, 0, 0, 2, 1, 0, 0, 0, 3, 0, + 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, + 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 7, 8, 0, 0, 0, 0, 9, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 5, 0, 0, 11, 0, 12, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 15, 0, 0, 0, 0, 5, 0, 0, 0, 16, 0, 0, 0, 10, 0, + 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 14, 18, 0, 19, 0, 0, 0, 20, 0, 0, 0, 0, 10, 0, + 0, 21, 0, 0, 0, 0, 0, 3, 0, 0, 1, 0, 0, 0, 22, 0, + 0, 0, 23, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 13, 0, 0, + 0, 13, 0, 0, 0, 17, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, + 0, 19, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 10, + 0, 8, 26, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 27, 0, 28, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_grapheme_link_table_3[] = { + 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 24, 0, 4, 0, 0, + 0, 0, 0, 4, 16, 0, 0, 0, 0, 0, 0, 6, 0, 0, 48, 0, + 0, 0, 16, 0, 0, 0, 4, 0, 1, 0, 0, 0, 0, 12, 0, 0, + 0, 0, 12, 0, 0, 0, 0, 128, 64, 0, 0, 0, 0, 16, 0, 0, + 0, 0, 8, 0, 0, 0, 64, 0, 0, 0, 1, 128, 0, 0, 0, 2, + 0, 0, 24, 0, 0, 0, 32, 0, 0, 192, 1, 0, 4, 0, 0, 0, + 0, 8, 0, 0, 0, 0, 0, 96, 128, 0, 0, 0, 48, 0, 0, 0, + 0, 0, 128, 0, 6, 0, 0, 0, 0, 128, 0, 0 +}; + +RE_UINT32 re_get_grapheme_link(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_grapheme_link_table_1[field_2]; + v = re_grapheme_link_table_2[(v << 5) | field_1]; + v = re_grapheme_link_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Hangul_Syllable_Type. */ +static RE_UINT8 re_hangul_syllable_type_table_1[] = { + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 4, 5, 6, 7, + 8, 9, 3, 4, 5, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_hangul_syllable_type_table_2[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 7, 8, 9, 10, 11, 12, 6, 7, 8, 9, 10, 11, 12, 6, 7, + 8, 9, 10, 11, 12, 6, 7, 8, 9, 10, 11, 12, 6, 7, 8, 9, + 10, 11, 12, 6, 7, 8, 9, 10, 11, 12, 6, 7, 8, 9, 10, 11, + 12, 6, 7, 8, 9, 10, 11, 12, 6, 7, 8, 9, 10, 11, 12, 6, + 7, 8, 9, 10, 11, 12, 6, 7, 8, 9, 10, 11, 12, 6, 7, 8, + 9, 10, 11, 12, 6, 7, 8, 9, 10, 11, 12, 6, 7, 8, 9, 10, + 11, 12, 6, 7, 8, 9, 10, 11, 12, 6, 7, 8, 9, 10, 11, 12, + 6, 7, 8, 9, 10, 11, 12, 6, 7, 8, 9, 10, 11, 12, 6, 7, + 8, 9, 10, 11, 12, 6, 7, 8, 9, 10, 11, 12, 6, 7, 8, 9, + 10, 11, 12, 6, 7, 8, 9, 10, 11, 12, 6, 7, 8, 9, 10, 11, + 12, 6, 7, 8, 9, 10, 11, 12, 6, 7, 8, 9, 10, 11, 12, 6, + 7, 8, 9, 10, 11, 12, 6, 7, 8, 9, 10, 11, 12, 6, 7, 8, + 9, 10, 11, 12, 6, 7, 8, 9, 10, 11, 12, 6, 7, 8, 9, 10, + 11, 12, 6, 7, 8, 9, 10, 11, 12, 6, 7, 8, 9, 10, 11, 12, + 11, 12, 6, 7, 8, 9, 10, 11, 12, 6, 7, 8, 9, 10, 11, 12, + 6, 7, 8, 9, 10, 11, 12, 6, 7, 8, 9, 10, 11, 13, 14, 15 +}; + +static RE_UINT8 re_hangul_syllable_type_table_3[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 4, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 4, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0 +}; + +RE_UINT32 re_get_hangul_syllable_type(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = codepoint & 0x1F; + + v = re_hangul_syllable_type_table_1[field_2]; + v = re_hangul_syllable_type_table_2[(v << 5) | field_1]; + v = re_hangul_syllable_type_table_3[(v << 5) | field_0]; + + return v; +} + +/* Hex_Digit. */ +RE_UINT32 re_get_hex_digit(RE_UINT32 codepoint) { + if (0x30 <= codepoint && codepoint <= 0x39) + return 1; + if (0x41 <= codepoint && codepoint <= 0x46) + return 1; + if (0x61 <= codepoint && codepoint <= 0x66) + return 1; + if (0xFF10 <= codepoint && codepoint <= 0xFF19) + return 1; + if (0xFF21 <= codepoint && codepoint <= 0xFF26) + return 1; + if (0xFF41 <= codepoint && codepoint <= 0xFF46) + return 1; + + return 0; +} + +/* Horiz_Space. */ +static RE_UINT8 re_horiz_space_table_1[] = { + 0, 1, 1, 1, 1, 2, 3, 1, 4, 1, 1, 1, 5, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +}; + +static RE_UINT8 re_horiz_space_table_2[] = { + 0, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 4, 5, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 +}; + +static RE_UINT8 re_horiz_space_table_3[] = { + 0, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, + 255, 7, 0, 0, 0, 128, 0, 0, 0, 0, 0, 128 +}; + +RE_UINT32 re_get_horiz_space(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_horiz_space_table_1[field_2]; + v = re_horiz_space_table_2[(v << 5) | field_1]; + v = re_horiz_space_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Hyphen. */ +static RE_UINT8 re_hyphen_table_1[] = { + 0, 1, 2, 2, 2, 2, 3, 2, 4, 2, 2, 5, 6, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 7, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 +}; + +static RE_UINT8 re_hyphen_table_2[] = { + 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 0 +}; + +static RE_UINT8 re_hyphen_table_3[] = { + 0, 0, 0, 0, 0, 32, 0, 0, 0, 4, 0, 0, 64, 0, 0, 0, + 0, 0, 3, 0, 0, 0, 128, 0, 0, 0, 0, 8, 8, 0, 0, 0, + 32, 0, 0, 0 +}; + +RE_UINT32 re_get_hyphen(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_hyphen_table_1[field_2]; + v = re_hyphen_table_2[(v << 5) | field_1]; + v = re_hyphen_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* ID_Compat_Math_Continue. */ +static RE_UINT8 re_id_compat_math_continue_table_1[] = { + 0, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +}; + +static RE_UINT8 re_id_compat_math_continue_table_2[] = { + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 5, 6, 7, 7, 8, 8, 9, 9, 10, 0 +}; + +static RE_UINT8 re_id_compat_math_continue_table_3[] = { + 0, 0, 0, 0, 0, 0, 12, 2, 0, 0, 241, 127, 255, 127, 0, 0, + 132, 0, 0, 64, 2, 0, 0, 8, 0, 0, 0, 8, 0, 0, 32, 0, + 0, 128, 0, 0, 0, 2, 0, 0, 8, 0, 0, 0 +}; + +RE_UINT32 re_get_id_compat_math_continue(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_id_compat_math_continue_table_1[field_2]; + v = re_id_compat_math_continue_table_2[(v << 5) | field_1]; + v = re_id_compat_math_continue_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* ID_Compat_Math_Start. */ +static RE_UINT8 re_id_compat_math_start_table_1[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_id_compat_math_start_table_2[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2, 3, 4, 4, 5, 5, 6, 6, 7, 0 +}; + +static RE_UINT8 re_id_compat_math_start_table_3[] = { + 0, 0, 0, 0, 132, 0, 0, 64, 2, 0, 0, 8, 0, 0, 0, 8, + 0, 0, 32, 0, 0, 128, 0, 0, 0, 2, 0, 0, 8, 0, 0, 0 +}; + +RE_UINT32 re_get_id_compat_math_start(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_id_compat_math_start_table_1[field_2]; + v = re_id_compat_math_start_table_2[(v << 5) | field_1]; + v = re_id_compat_math_start_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* ID_Continue. */ +static RE_UINT8 re_id_continue_table_1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 11, 12, 12, 12, + 12, 12, 12, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 14, 15, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 16, 9, 9, 9, 9, 9, 9, 9, 9, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 9, 29, 12, 30, 12, 12, + 31, 32, 9, 9, 9, 9, 9, 9, 33, 9, 34, 35, 12, 12, 12, 12, + 12, 36, 12, 37, 9, 9, 9, 9, 9, 9, 9, 38, 39, 9, 9, 40, + 9, 9, 9, 41, 42, 43, 44, 45, 46, 47, 48, 49, 9, 9, 50, 9, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 51, 12, 12, 12, 52, 53, 12, + 12, 12, 12, 54, 12, 12, 12, 12, 12, 12, 55, 56, 9, 9, 57, 9, + 12, 12, 12, 12, 58, 12, 12, 12, 59, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 60, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 +}; + +static RE_UINT16 re_id_continue_table_2[] = { + 0, 1, 2, 3, 0, 4, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 7, 8, 6, 6, 6, 9, 10, 11, 6, 12, + 6, 6, 6, 6, 13, 6, 6, 6, 6, 14, 15, 6, 16, 17, 18, 19, + 20, 6, 6, 21, 6, 6, 22, 23, 24, 6, 25, 6, 6, 26, 6, 27, + 6, 28, 29, 30, 31, 6, 6, 11, 6, 6, 6, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 42, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 52, 6, 60, 61, 62, 63, 64, 65, + 66, 67, 68, 0, 69, 70, 71, 0, 72, 73, 74, 75, 76, 77, 78, 0, + 6, 6, 79, 6, 80, 6, 81, 82, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 83, 6, 84, 85, 86, 6, 87, 6, 88, 89, 90, 6, 6, 91, + 66, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 92, 3, 6, 6, 93, 94, 95, 96, 97, 6, 6, 98, 99, + 100, 6, 6, 101, 6, 30, 6, 102, 103, 104, 105, 106, 6, 107, 108, 0, + 29, 6, 103, 109, 110, 111, 112, 0, 6, 6, 113, 114, 6, 6, 6, 96, + 6, 115, 116, 80, 30, 88, 117, 67, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 91, 6, 118, 80, 6, 119, 120, 121, + 122, 123, 124, 125, 126, 0, 126, 127, 128, 129, 130, 6, 131, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 6, 6, 6, 6, 6, 6, 132, 6, 81, 6, 133, 134, 135, 135, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 136, 137, 66, 6, 138, 66, 6, 6, 139, 14, 6, 6, 112, 6, 0, 24, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 0, 0, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 140, 0, 24, 80, 6, 6, 6, 6, 6, 6, 6, 6, + 141, 142, 6, 143, 6, 6, 6, 26, 144, 145, 6, 6, 146, 6, 147, 148, + 6, 149, 6, 96, 6, 6, 150, 151, 6, 152, 96, 77, 6, 6, 153, 103, + 6, 134, 154, 155, 6, 6, 156, 157, 158, 159, 82, 79, 6, 6, 6, 160, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 161, 162, 29, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 152, 6, 6, 163, 0, 164, 165, 166, 6, 6, 26, 167, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 80, 24, 6, 168, 6, 169, 170, + 90, 171, 172, 173, 6, 6, 6, 77, 1, 2, 3, 139, 6, 103, 174, 0, + 175, 176, 177, 0, 6, 6, 6, 67, 0, 0, 6, 95, 0, 0, 0, 178, + 0, 0, 0, 0, 77, 6, 179, 180, 6, 181, 30, 67, 80, 6, 182, 0, + 6, 6, 6, 6, 80, 79, 183, 29, 6, 184, 6, 185, 186, 187, 6, 96, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 134, 102, 169, 188, 189, 0, 0, + 190, 191, 102, 134, 103, 0, 0, 192, 102, 163, 0, 0, 6, 193, 0, 0, + 194, 195, 0, 77, 77, 0, 74, 196, 6, 102, 102, 197, 26, 0, 0, 0, + 6, 6, 131, 0, 6, 197, 6, 197, 6, 198, 6, 199, 200, 0, 0, 0, + 0, 0, 0, 0, 6, 201, 202, 203, 77, 204, 179, 24, 200, 24, 205, 134, + 6, 6, 196, 206, 6, 67, 207, 208, 6, 209, 210, 211, 6, 6, 212, 0, + 213, 193, 214, 0, 215, 216, 6, 217, 33, 218, 219, 220, 221, 12, 222, 223, + 6, 6, 224, 214, 6, 6, 225, 0, 0, 0, 0, 0, 6, 226, 227, 0, + 6, 6, 228, 0, 6, 101, 79, 229, 88, 230, 196, 0, 0, 0, 0, 0, + 6, 67, 0, 0, 0, 6, 6, 231, 232, 233, 234, 0, 0, 235, 236, 237, + 6, 103, 204, 6, 238, 24, 6, 101, 0, 0, 0, 0, 0, 0, 6, 239, + 240, 5, 239, 148, 168, 241, 0, 0, 242, 243, 198, 244, 245, 99, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 134, 246, 247, 248, 0, 0, 249, 0, 0, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 163, 0, 0, 0, + 6, 6, 6, 112, 6, 6, 6, 6, 6, 6, 229, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 6, 6, 179, + 6, 90, 102, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 67, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 163, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 101, 103, 79, 6, 103, 79, 106, 6, 134, 234, 250, 90, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 113, 0, 0, 0, 0, + 0, 0, 6, 6, 0, 0, 0, 0, 6, 6, 251, 6, 252, 0, 0, 253, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 115, + 6, 6, 6, 6, 6, 6, 102, 123, 131, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 255, 256, 210, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 29, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 6, 6, 257, 258, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 152, 196, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 259, 260, 261, 0, 0, + 0, 0, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 6, 209, 6, 262, 263, 264, 6, 265, 266, 267, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 268, 269, 82, 209, 209, 270, 270, 240, 240, 271, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 272, 6, 273, 274, 275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 103, 276, 0, 0, 0, 0, 0, 0, + 277, 278, 6, 28, 279, 0, 0, 0, 6, 280, 281, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 24, 112, 6, 163, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 24, 163, 0, 0, 0, 0, 0, 0, 24, 67, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 282, + 6, 6, 6, 6, 6, 6, 283, 0, 6, 6, 230, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 264, 284, 285, 286, 287, 288, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 0, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 163, 6, 6, 6, 6, 6, 6, + 80, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 289, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 290, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 30, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 90, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, 90, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_id_continue_table_3[] = { + 0, 0, 0, 0, 0, 0, 255, 3, 254, 255, 255, 135, 254, 255, 255, 7, + 0, 4, 160, 4, 255, 255, 127, 255, 255, 255, 255, 255, 195, 255, 3, 0, + 31, 80, 0, 0, 255, 255, 223, 188, 192, 215, 255, 255, 251, 255, 255, 255, + 255, 255, 191, 255, 251, 252, 255, 255, 255, 255, 254, 255, 255, 255, 127, 2, + 255, 1, 254, 255, 255, 255, 255, 191, 182, 0, 255, 255, 255, 135, 7, 0, + 0, 0, 255, 7, 255, 195, 255, 255, 255, 255, 239, 159, 255, 253, 255, 159, + 0, 0, 255, 255, 255, 231, 255, 255, 255, 255, 3, 0, 255, 255, 63, 36, + 255, 63, 0, 0, 255, 255, 255, 15, 255, 7, 255, 255, 255, 126, 128, 255, + 207, 255, 254, 255, 239, 159, 249, 255, 255, 253, 197, 243, 159, 121, 128, 176, + 207, 255, 3, 80, 238, 135, 249, 255, 255, 253, 109, 211, 135, 57, 2, 94, + 192, 255, 63, 0, 238, 191, 251, 255, 255, 253, 237, 243, 191, 59, 1, 0, + 207, 255, 0, 254, 238, 159, 249, 255, 159, 57, 224, 176, 207, 255, 2, 0, + 236, 199, 61, 214, 24, 199, 255, 195, 199, 61, 129, 0, 192, 255, 0, 0, + 255, 223, 253, 255, 255, 253, 255, 243, 223, 61, 96, 39, 207, 255, 0, 0, + 239, 223, 253, 255, 255, 253, 239, 243, 223, 61, 96, 96, 207, 255, 14, 0, + 223, 125, 240, 128, 207, 255, 0, 252, 238, 255, 127, 252, 255, 255, 251, 47, + 127, 132, 95, 255, 192, 255, 12, 0, 254, 255, 255, 255, 255, 255, 255, 7, + 255, 127, 255, 3, 214, 247, 255, 255, 175, 255, 255, 63, 95, 127, 255, 243, + 1, 0, 0, 3, 255, 3, 160, 194, 255, 254, 255, 255, 255, 31, 254, 255, + 223, 255, 255, 254, 255, 255, 255, 31, 64, 0, 0, 0, 255, 3, 255, 255, + 255, 255, 255, 63, 191, 32, 255, 255, 255, 255, 255, 247, 255, 61, 127, 61, + 255, 61, 255, 255, 255, 255, 61, 127, 61, 255, 127, 255, 255, 255, 61, 255, + 255, 255, 255, 231, 0, 254, 3, 0, 255, 255, 0, 0, 255, 255, 63, 63, + 255, 159, 255, 255, 255, 199, 255, 1, 255, 255, 63, 128, 255, 255, 31, 0, + 255, 255, 15, 0, 255, 223, 13, 0, 255, 255, 143, 48, 255, 3, 0, 0, + 0, 184, 255, 3, 255, 255, 255, 1, 255, 255, 63, 0, 255, 255, 255, 127, + 255, 15, 255, 15, 192, 255, 255, 255, 255, 63, 31, 0, 255, 15, 255, 255, + 255, 3, 255, 7, 255, 255, 255, 159, 255, 3, 255, 3, 128, 0, 255, 191, + 255, 127, 0, 0, 255, 31, 255, 3, 0, 248, 15, 0, 255, 255, 255, 0, + 255, 227, 255, 255, 0, 0, 247, 255, 63, 63, 255, 170, 255, 255, 223, 95, + 220, 31, 207, 15, 255, 31, 220, 31, 0, 48, 0, 0, 0, 0, 0, 128, + 1, 0, 16, 0, 0, 0, 2, 128, 0, 0, 255, 31, 226, 255, 1, 0, + 132, 252, 47, 63, 80, 253, 255, 243, 224, 67, 0, 0, 255, 1, 0, 0, + 31, 248, 15, 0, 255, 128, 0, 128, 255, 255, 127, 0, 127, 127, 127, 127, + 224, 0, 0, 0, 254, 255, 62, 31, 255, 255, 127, 254, 224, 255, 255, 255, + 255, 31, 0, 0, 255, 31, 255, 255, 255, 15, 0, 0, 255, 255, 240, 191, + 0, 0, 128, 255, 252, 255, 255, 255, 255, 249, 255, 255, 255, 63, 235, 31, + 0, 0, 252, 255, 255, 16, 0, 0, 63, 0, 255, 3, 255, 255, 255, 232, + 255, 63, 255, 255, 1, 128, 255, 3, 255, 63, 255, 3, 255, 255, 127, 252, + 7, 0, 0, 56, 255, 255, 124, 0, 126, 126, 126, 0, 127, 127, 255, 255, + 255, 55, 255, 3, 15, 0, 255, 255, 127, 248, 255, 255, 255, 255, 255, 3, + 127, 0, 248, 224, 255, 253, 127, 95, 219, 255, 255, 255, 0, 0, 248, 255, + 255, 255, 252, 255, 255, 0, 0, 0, 0, 0, 255, 15, 255, 255, 24, 0, + 0, 224, 0, 0, 0, 0, 223, 255, 252, 252, 252, 28, 255, 239, 255, 255, + 127, 255, 255, 183, 255, 63, 255, 63, 0, 0, 0, 32, 255, 255, 1, 0, + 1, 0, 0, 0, 0, 224, 255, 255, 15, 255, 62, 0, 255, 255, 15, 255, + 255, 0, 255, 255, 15, 0, 255, 247, 255, 247, 183, 255, 251, 255, 251, 27, + 191, 255, 255, 255, 255, 255, 253, 7, 63, 253, 255, 255, 255, 255, 191, 145, + 255, 255, 55, 0, 255, 255, 255, 192, 111, 240, 239, 254, 255, 255, 63, 135, + 127, 0, 0, 0, 255, 255, 7, 0, 255, 0, 255, 3, 63, 190, 255, 255, + 63, 0, 0, 0, 255, 27, 3, 0, 28, 0, 0, 0, 0, 0, 0, 240, + 128, 0, 255, 255, 31, 0, 0, 0, 192, 255, 63, 128, 4, 0, 255, 255, + 255, 1, 255, 3, 255, 255, 223, 255, 240, 0, 255, 255, 255, 255, 79, 0, + 31, 222, 255, 23, 255, 255, 251, 255, 3, 0, 0, 0, 127, 189, 255, 191, + 255, 1, 255, 255, 255, 7, 255, 3, 255, 253, 237, 251, 159, 57, 129, 224, + 207, 31, 31, 0, 255, 75, 255, 255, 165, 247, 15, 0, 6, 0, 0, 0, + 255, 7, 255, 195, 191, 0, 255, 3, 255, 255, 63, 255, 1, 0, 0, 63, + 17, 0, 255, 3, 15, 0, 0, 0, 255, 15, 255, 3, 255, 3, 0, 128, + 127, 242, 111, 255, 255, 255, 191, 249, 15, 0, 255, 3, 255, 252, 255, 255, + 255, 255, 255, 252, 27, 0, 0, 0, 255, 255, 255, 35, 1, 0, 255, 3, + 255, 253, 255, 255, 255, 254, 127, 0, 127, 251, 255, 255, 255, 255, 127, 180, + 191, 253, 255, 255, 255, 127, 251, 1, 255, 255, 253, 255, 255, 255, 255, 199, + 7, 0, 255, 7, 0, 0, 1, 0, 248, 255, 255, 224, 255, 135, 255, 255, + 255, 128, 255, 255, 27, 0, 3, 0, 0, 0, 239, 111, 7, 0, 4, 0, + 0, 0, 39, 0, 255, 7, 255, 31, 255, 1, 255, 99, 224, 227, 7, 248, + 231, 15, 0, 0, 0, 60, 0, 0, 255, 255, 255, 223, 100, 222, 255, 235, + 239, 255, 255, 255, 191, 231, 223, 223, 255, 255, 255, 123, 95, 252, 253, 255, + 63, 255, 255, 255, 253, 255, 255, 247, 255, 127, 255, 255, 247, 207, 255, 255, + 255, 255, 127, 248, 255, 31, 32, 0, 16, 0, 0, 248, 254, 255, 0, 0, + 224, 7, 0, 0, 127, 255, 255, 249, 219, 7, 255, 255, 0, 128, 0, 0, + 255, 31, 255, 63, 255, 67, 0, 0, 127, 111, 255, 127, 31, 0, 127, 0, + 150, 254, 247, 10, 132, 234, 150, 170, 150, 247, 247, 94, 255, 251, 255, 15, + 238, 251, 255, 15, 3, 0, 255, 255, 1, 0, 255, 255 +}; + +RE_UINT32 re_get_id_continue(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_id_continue_table_1[field_2]; + v = re_id_continue_table_2[(v << 5) | field_1]; + v = re_id_continue_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Ideographic. */ +static RE_UINT8 re_ideographic_table_1[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, + 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 2, 2, 2, 2, + 2, 6, 2, 7, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 10, 11, 2, + 2, 2, 2, 12, 2, 2, 2, 2, 2, 2, 13, 14, 0, 0, 15, 0, + 2, 2, 2, 2, 16, 2, 2, 2, 17, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_ideographic_table_2[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 4, 3, 3, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, + 3, 3, 3, 3, 3, 3, 8, 9, 10, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 12, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 3, 3, 3, 3, 3, + 13, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 14, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 15, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 16, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 17, 0, 0 +}; + +static RE_UINT8 re_ideographic_table_3[] = { + 0, 0, 0, 0, 192, 0, 0, 0, 254, 3, 0, 7, 255, 255, 255, 255, + 255, 63, 255, 255, 255, 255, 255, 3, 16, 0, 0, 0, 255, 255, 255, 0, + 255, 255, 63, 0, 0, 0, 0, 128, 255, 1, 0, 0, 0, 0, 255, 255, + 255, 255, 255, 15, 255, 255, 255, 63, 3, 0, 255, 255, 1, 0, 255, 255, + 255, 7, 255, 255, 255, 255, 0, 0 +}; + +RE_UINT32 re_get_ideographic(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_ideographic_table_1[field_2]; + v = re_ideographic_table_2[(v << 5) | field_1]; + v = re_ideographic_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* IDS_Binary_Operator. */ +RE_UINT32 re_get_ids_binary_operator(RE_UINT32 codepoint) { + if (0x2FF0 <= codepoint && codepoint <= 0x2FF1) + return 1; + if (0x2FF4 <= codepoint && codepoint <= 0x2FFD) + return 1; + if (codepoint == 0x31EF) + return 1; + + return 0; +} + +/* ID_Start. */ +static RE_UINT8 re_id_start_table_1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 11, 12, 12, 12, + 12, 12, 12, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 14, 15, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 16, 9, 9, 9, 9, 9, 9, 9, 9, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 9, 29, 12, 30, 12, 12, + 31, 32, 9, 9, 9, 9, 9, 9, 33, 9, 34, 35, 12, 12, 12, 12, + 12, 36, 12, 37, 9, 9, 9, 9, 9, 9, 9, 38, 39, 9, 9, 40, + 9, 9, 9, 9, 9, 41, 9, 42, 43, 44, 45, 46, 9, 9, 9, 9, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 47, 12, 12, 12, 48, 49, 12, + 12, 12, 12, 50, 12, 12, 12, 12, 12, 12, 51, 52, 9, 9, 53, 9, + 12, 12, 12, 12, 54, 12, 12, 12, 55, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 +}; + +static RE_UINT16 re_id_start_table_2[] = { + 0, 0, 1, 1, 0, 2, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 5, 6, 0, 0, 0, 7, 8, 9, 4, 10, + 4, 4, 4, 4, 11, 4, 4, 4, 4, 12, 13, 4, 14, 0, 15, 16, + 0, 4, 17, 18, 4, 4, 19, 20, 21, 22, 23, 4, 4, 24, 25, 26, + 27, 28, 29, 30, 31, 4, 32, 0, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 46, 50, 51, 52, 53, 47, 0, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 0, + 69, 70, 68, 0, 71, 72, 73, 0, 74, 0, 75, 76, 77, 0, 0, 0, + 4, 78, 79, 80, 81, 4, 82, 83, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 84, 4, 85, 86, 87, 4, 88, 4, 89, 0, 22, 4, 4, 90, + 69, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 91, 1, 4, 4, 92, 93, 94, 94, 95, 4, 96, 97, 0, + 0, 4, 4, 29, 4, 98, 4, 99, 100, 0, 15, 101, 4, 102, 32, 0, + 103, 4, 104, 0, 0, 105, 0, 0, 106, 96, 107, 0, 108, 109, 4, 110, + 4, 111, 112, 113, 30, 114, 0, 115, 4, 4, 4, 4, 4, 4, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 90, 4, 116, 113, 4, 117, 118, 119, + 0, 0, 0, 120, 121, 0, 0, 0, 122, 123, 124, 4, 14, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 125, 4, 82, 4, 126, 103, 127, 127, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 128, 129, 69, 4, 130, 69, 4, 83, 106, 12, 4, 4, 131, 4, 0, 15, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 76, 0, 15, 113, 4, 4, 4, 4, 4, 4, 4, 4, + 132, 133, 4, 134, 113, 4, 4, 22, 135, 136, 4, 4, 137, 4, 138, 139, + 140, 141, 4, 96, 136, 96, 0, 142, 25, 143, 68, 144, 33, 145, 146, 147, + 4, 14, 148, 149, 4, 150, 151, 152, 153, 154, 83, 155, 4, 4, 4, 141, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 156, 157, 158, + 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 159, 4, 4, 160, 0, 161, 162, 163, 4, 4, 94, 164, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 113, 15, 4, 165, 4, 166, 167, + 0, 0, 0, 168, 4, 4, 4, 144, 0, 1, 1, 169, 4, 100, 170, 0, + 171, 172, 173, 0, 4, 4, 4, 89, 0, 0, 4, 104, 0, 0, 0, 0, + 0, 0, 0, 0, 144, 4, 174, 0, 4, 23, 30, 99, 113, 4, 175, 0, + 4, 4, 4, 4, 113, 15, 176, 158, 4, 177, 4, 178, 179, 180, 4, 96, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 103, 99, 166, 181, 182, 0, 0, + 183, 184, 99, 103, 100, 0, 0, 185, 99, 160, 0, 0, 4, 186, 0, 0, + 187, 99, 0, 144, 144, 0, 75, 188, 4, 99, 99, 145, 94, 0, 0, 0, + 4, 4, 14, 0, 4, 145, 4, 145, 4, 111, 25, 189, 110, 0, 0, 0, + 0, 0, 0, 0, 4, 190, 191, 0, 144, 192, 110, 15, 57, 15, 188, 103, + 108, 193, 0, 194, 108, 22, 15, 14, 108, 68, 195, 196, 108, 145, 197, 0, + 198, 199, 74, 0, 200, 201, 100, 0, 49, 46, 202, 57, 203, 204, 205, 0, + 4, 104, 206, 57, 4, 22, 207, 0, 0, 0, 0, 0, 4, 131, 208, 0, + 4, 22, 209, 0, 4, 210, 0, 0, 89, 0, 68, 0, 0, 0, 0, 0, + 4, 211, 0, 0, 0, 4, 4, 212, 213, 214, 215, 0, 0, 216, 174, 217, + 218, 219, 220, 4, 221, 15, 4, 29, 0, 0, 0, 0, 0, 0, 4, 74, + 222, 131, 74, 139, 22, 0, 0, 0, 223, 174, 224, 225, 226, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 145, 227, 96, 0, 0, 0, 47, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 160, 0, 0, 0, + 4, 4, 4, 131, 4, 4, 4, 4, 4, 4, 111, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 4, 4, 174, + 4, 22, 228, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 89, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 113, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 29, 100, 15, 4, 100, 15, 229, 4, 22, 111, 230, 22, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 76, 0, 0, 0, 0, + 0, 0, 4, 4, 0, 0, 0, 0, 4, 4, 231, 0, 164, 0, 0, 232, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 193, + 4, 4, 4, 4, 4, 4, 99, 212, 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 234, 235, 236, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 158, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 237, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 239, 4, 240, 241, 242, 4, 243, 244, 245, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 246, 247, 83, 239, 239, 248, 248, 222, 222, 148, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 100, 249, 0, 0, 0, 0, 0, 0, + 0, 15, 4, 229, 0, 0, 0, 0, 4, 250, 251, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 15, 229, 4, 211, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 15, 211, 0, 0, 0, 0, 0, 0, 15, 252, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253, + 4, 4, 4, 4, 4, 4, 188, 0, 4, 4, 254, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 242, 255, 256, 257, 258, 259, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 160, 4, 4, 4, 4, 4, 4, + 113, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 260, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 261, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 113, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 113, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 30, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 22, 0, 0 +}; + +static RE_UINT8 re_id_start_table_3[] = { + 0, 0, 0, 0, 254, 255, 255, 7, 0, 4, 32, 4, 255, 255, 127, 255, + 255, 255, 255, 255, 195, 255, 3, 0, 31, 80, 0, 0, 0, 0, 223, 188, + 64, 215, 255, 255, 251, 255, 255, 255, 255, 255, 191, 255, 3, 252, 255, 255, + 255, 255, 254, 255, 255, 255, 127, 2, 255, 1, 0, 0, 0, 0, 255, 255, + 255, 135, 7, 0, 255, 7, 0, 0, 0, 192, 254, 255, 255, 255, 47, 0, + 96, 192, 0, 156, 0, 0, 253, 255, 255, 255, 0, 0, 0, 224, 255, 255, + 63, 0, 2, 0, 0, 252, 255, 255, 255, 7, 48, 4, 255, 255, 63, 4, + 16, 1, 0, 0, 255, 255, 255, 1, 255, 7, 255, 255, 255, 126, 0, 0, + 255, 3, 0, 0, 240, 255, 255, 255, 255, 255, 255, 35, 0, 0, 1, 255, + 3, 0, 254, 255, 225, 159, 249, 255, 255, 253, 197, 35, 0, 64, 0, 176, + 3, 0, 3, 16, 224, 135, 249, 255, 255, 253, 109, 3, 0, 0, 0, 94, + 0, 0, 28, 0, 224, 191, 251, 255, 255, 253, 237, 35, 0, 0, 1, 0, + 3, 0, 0, 2, 224, 159, 249, 255, 0, 0, 0, 176, 3, 0, 2, 0, + 232, 199, 61, 214, 24, 199, 255, 3, 224, 223, 253, 255, 255, 253, 255, 35, + 0, 0, 0, 39, 3, 0, 0, 0, 225, 223, 253, 255, 255, 253, 239, 35, + 0, 0, 0, 96, 3, 0, 6, 0, 240, 223, 253, 255, 255, 255, 255, 39, + 0, 64, 112, 128, 3, 0, 0, 252, 224, 255, 127, 252, 255, 255, 251, 47, + 127, 0, 0, 0, 254, 255, 255, 255, 255, 255, 13, 0, 214, 247, 255, 255, + 175, 255, 13, 32, 95, 0, 0, 240, 1, 0, 0, 0, 255, 254, 255, 255, + 255, 31, 0, 0, 0, 31, 0, 0, 255, 7, 0, 128, 0, 0, 63, 60, + 98, 192, 225, 255, 3, 64, 0, 0, 191, 32, 255, 255, 255, 255, 255, 247, + 255, 61, 127, 61, 255, 61, 255, 255, 255, 255, 61, 127, 61, 255, 127, 255, + 255, 255, 61, 255, 255, 255, 255, 7, 255, 255, 63, 63, 255, 159, 255, 255, + 255, 199, 255, 1, 255, 255, 3, 128, 255, 255, 3, 0, 255, 223, 1, 0, + 255, 255, 15, 0, 0, 0, 128, 16, 255, 5, 255, 255, 255, 255, 63, 0, + 255, 255, 255, 127, 255, 63, 31, 0, 255, 15, 255, 255, 255, 255, 127, 0, + 255, 255, 31, 0, 128, 0, 0, 0, 224, 255, 255, 255, 224, 31, 0, 0, + 248, 255, 255, 255, 1, 192, 0, 252, 63, 0, 0, 0, 15, 0, 0, 0, + 0, 224, 0, 252, 255, 255, 255, 63, 255, 255, 255, 231, 0, 222, 111, 4, + 63, 63, 255, 170, 255, 255, 223, 95, 220, 31, 207, 15, 255, 31, 220, 31, + 0, 0, 2, 128, 0, 0, 255, 31, 132, 252, 47, 63, 80, 253, 255, 243, + 224, 67, 0, 0, 31, 120, 12, 0, 255, 128, 0, 0, 127, 127, 127, 127, + 224, 0, 0, 0, 254, 3, 62, 31, 255, 255, 127, 248, 255, 127, 0, 0, + 255, 31, 255, 255, 0, 12, 0, 0, 255, 127, 0, 128, 0, 0, 128, 255, + 252, 255, 255, 255, 255, 249, 255, 255, 255, 63, 235, 31, 0, 0, 252, 255, + 187, 247, 255, 255, 7, 0, 0, 0, 0, 0, 252, 104, 63, 0, 255, 255, + 255, 255, 255, 31, 255, 255, 7, 0, 0, 128, 0, 0, 223, 255, 0, 124, + 247, 15, 0, 0, 255, 255, 127, 196, 255, 255, 98, 62, 5, 0, 0, 56, + 255, 7, 28, 0, 126, 126, 126, 0, 127, 127, 255, 255, 255, 3, 255, 255, + 15, 0, 255, 255, 127, 248, 255, 255, 255, 255, 255, 15, 255, 63, 255, 255, + 255, 255, 255, 3, 127, 0, 248, 160, 255, 253, 127, 95, 219, 255, 255, 255, + 0, 0, 248, 255, 255, 255, 252, 255, 255, 0, 0, 0, 0, 0, 255, 15, + 0, 0, 223, 255, 192, 255, 255, 255, 252, 252, 252, 28, 255, 239, 255, 255, + 127, 255, 255, 183, 255, 63, 255, 63, 255, 255, 1, 0, 15, 255, 62, 0, + 255, 255, 15, 255, 255, 0, 255, 255, 15, 0, 255, 247, 255, 247, 183, 255, + 251, 255, 251, 27, 191, 255, 255, 255, 255, 255, 253, 7, 63, 253, 255, 255, + 255, 255, 191, 145, 255, 255, 55, 0, 255, 255, 255, 192, 1, 0, 239, 254, + 31, 0, 0, 0, 63, 128, 255, 255, 255, 3, 3, 0, 28, 0, 0, 0, + 128, 0, 255, 255, 255, 255, 255, 0, 0, 0, 38, 0, 144, 0, 255, 255, + 255, 255, 71, 0, 30, 0, 0, 20, 255, 255, 251, 255, 255, 15, 0, 128, + 127, 189, 255, 191, 255, 1, 255, 255, 0, 0, 1, 224, 255, 75, 255, 255, + 255, 255, 191, 0, 0, 0, 10, 0, 128, 7, 0, 128, 176, 0, 0, 0, + 0, 0, 0, 15, 16, 0, 0, 0, 255, 7, 0, 1, 255, 15, 0, 0, + 0, 0, 0, 128, 127, 242, 111, 255, 255, 255, 0, 128, 2, 0, 0, 0, + 255, 252, 255, 255, 10, 0, 0, 0, 1, 248, 255, 255, 255, 255, 7, 4, + 0, 0, 1, 240, 255, 3, 0, 32, 255, 253, 255, 255, 127, 251, 255, 255, + 64, 0, 0, 0, 191, 253, 255, 255, 255, 3, 0, 1, 244, 255, 253, 255, + 126, 0, 0, 0, 255, 63, 0, 0, 248, 255, 255, 224, 255, 7, 1, 0, + 11, 0, 0, 0, 0, 0, 239, 111, 7, 0, 4, 0, 0, 0, 39, 0, + 240, 0, 255, 255, 255, 7, 255, 31, 255, 1, 255, 3, 255, 255, 223, 255, + 255, 255, 255, 223, 100, 222, 255, 235, 239, 255, 255, 255, 191, 231, 223, 223, + 255, 255, 255, 123, 95, 252, 253, 255, 63, 255, 255, 255, 253, 255, 255, 247, + 255, 127, 255, 255, 224, 7, 0, 0, 255, 31, 128, 63, 0, 64, 0, 0, + 255, 63, 1, 0, 127, 111, 255, 127, 15, 8, 0, 0, 150, 254, 247, 10, + 132, 234, 150, 170, 150, 247, 247, 94, 255, 251, 255, 15, 238, 251, 255, 15, + 3, 0, 255, 255, 1, 0, 255, 255 +}; + +RE_UINT32 re_get_id_start(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_id_start_table_1[field_2]; + v = re_id_start_table_2[(v << 5) | field_1]; + v = re_id_start_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* IDS_Trinary_Operator. */ +RE_UINT32 re_get_ids_trinary_operator(RE_UINT32 codepoint) { + if (0x2FF2 <= codepoint && codepoint <= 0x2FF3) + return 1; + + return 0; +} + +/* IDS_Unary_Operator. */ +RE_UINT32 re_get_ids_unary_operator(RE_UINT32 codepoint) { + if (0x2FFE <= codepoint && codepoint <= 0x2FFF) + return 1; + + return 0; +} + +/* Indic_Conjunct_Break. */ +static RE_UINT8 re_indic_conjunct_break_table_1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 11, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 12, 13, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 14, 15, + 16, 9, 17, 18, 19, 20, 21, 22, 9, 9, 9, 9, 9, 23, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 24, 9, 25, 26, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 27, + 9, 9, 9, 28, 29, 9, 30, 9, 31, 32, 33, 9, 34, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 35, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 +}; + +static RE_UINT8 re_indic_conjunct_break_table_2[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 5, 6, 0, + 7, 0, 8, 9, 0, 0, 10, 11, 12, 13, 14, 0, 0, 15, 0, 16, + 17, 18, 19, 0, 20, 0, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 27, 39, 40, 41, 42, 43, 44, 0, + 45, 46, 47, 48, 49, 50, 51, 48, 52, 53, 54, 48, 49, 0, 55, 0, + 0, 56, 57, 0, 0, 58, 59, 0, 60, 61, 0, 62, 63, 64, 65, 0, + 0, 66, 67, 68, 69, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 71, 72, 73, 73, 0, 74, 75, 0, + 76, 0, 0, 0, 77, 78, 0, 0, 0, 79, 0, 0, 0, 0, 0, 0, + 80, 0, 81, 82, 0, 13, 83, 0, 84, 85, 86, 87, 88, 89, 0, 90, + 0, 91, 0, 0, 0, 0, 92, 93, 0, 0, 0, 0, 0, 0, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 94, 0, 0, 0, 0, 0, 13, 95, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 97, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 98, 0, 0, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 100, 101, 0, 0, 102, 0, 0, 0, 0, 0, 0, 0, 0, + 103, 104, 0, 0, 0, 0, 105, 106, 0, 107, 108, 0, 109, 110, 111, 112, + 0, 113, 114, 32, 0, 115, 49, 116, 0, 0, 0, 0, 0, 0, 0, 117, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 43, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, + 0, 0, 0, 0, 0, 0, 0, 111, 0, 0, 0, 119, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 120, 121, 0, 0, 0, 0, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 0, 123, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 124, 0, 125, 0, 0, 15, 0, 126, 0, 0, 0, + 49, 127, 128, 129, 88, 130, 42, 0, 109, 131, 0, 132, 88, 133, 134, 0, + 0, 135, 49, 0, 0, 0, 97, 136, 88, 137, 44, 138, 0, 139, 140, 31, + 0, 127, 141, 0, 0, 142, 143, 0, 0, 0, 0, 0, 0, 144, 145, 0, + 0, 146, 111, 0, 0, 147, 0, 0, 148, 149, 0, 0, 0, 0, 0, 0, + 0, 150, 0, 0, 0, 0, 0, 0, 0, 151, 152, 0, 0, 0, 153, 111, + 154, 155, 156, 0, 157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 158, 0, 0, 159, 160, 0, 0, 0, 161, 162, 0, 163, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 164, 88, 119, 165, 0, 0, 0, 0, 0, + 0, 0, 166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 101, 167, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 168, 0, 169, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170, 0, 171, 0, 0, 172, + 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 174, 128, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 175, 176, 177, 0, 0, + 0, 0, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 178, 1, 179, 180, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 182, 183, 0, 0, 170, 0, 0, 0, 0, 169, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 184, 0, 185, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 185, 0, 0, 0, 0, 0, 0, 0, 186, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 169, 0, 0, 0, 187, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 188, + 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_indic_conjunct_break_table_3[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, + 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, + 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 1, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 3, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, + 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, + 2, 0, 2, 0, 0, 0, 2, 2, 2, 2, 0, 0, 1, 0, 1, 0, + 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 2, 0, 2, + 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, + 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 0, 0, 1, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, + 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 0, 0, 1, 0, 1, 1, + 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 2, 2, 0, 2, + 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 1, 0, 1, 1, + 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 3, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 2, 2, 2, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, + 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 0, 1, 0, + 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, + 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, + 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, + 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, + 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, + 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, + 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, + 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, + 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1 +}; + +RE_UINT32 re_get_indic_conjunct_break(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = codepoint & 0x1F; + + v = re_indic_conjunct_break_table_1[field_2]; + v = re_indic_conjunct_break_table_2[(v << 5) | field_1]; + v = re_indic_conjunct_break_table_3[(v << 5) | field_0]; + + return v; +} + +/* Indic_Positional_Category. */ +static RE_UINT8 re_indic_positional_category_table_1[] = { + 0, 0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 9, 0, 10, 11, 12, 13, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 15, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_indic_positional_category_table_2[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, + 9, 6, 10, 11, 9, 6, 12, 13, 5, 14, 15, 4, 16, 17, 18, 0, + 19, 20, 21, 4, 5, 14, 22, 23, 24, 25, 26, 4, 5, 0, 27, 28, + 0, 29, 30, 0, 0, 31, 32, 0, 33, 34, 0, 35, 36, 37, 38, 0, + 0, 39, 40, 41, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 43, 44, 45, 45, 0, 46, 47, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 0, 0, 49, 50, 0, + 51, 0, 52, 53, 0, 0, 0, 0, 54, 55, 56, 57, 58, 59, 0, 60, + 0, 61, 0, 0, 0, 0, 62, 63, 0, 0, 0, 0, 0, 0, 0, 64, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 66, 67, 0, 0, 68, 69, 70, 71, 0, 72, 73, 0, 1, 74, 75, 76, + 0, 77, 78, 79, 0, 80, 81, 82, 0, 0, 0, 0, 0, 0, 0, 83, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 84, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 86, 87, 88, 89, 58, 90, 91, 0, 92, 93, 94, 95, 58, 96, 97, 0, + 0, 98, 99, 0, 0, 0, 100, 101, 24, 102, 103, 104, 0, 105, 106, 107, + 0, 108, 109, 0, 0, 110, 111, 0, 0, 0, 0, 0, 0, 112, 113, 0, + 0, 114, 115, 0, 0, 116, 0, 0, 117, 118, 0, 0, 0, 0, 0, 0, + 0, 119, 0, 0, 0, 0, 0, 0, 0, 120, 121, 0, 0, 0, 122, 123, + 124, 125, 126, 0, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 128, 0, 0, 129, 130, 0, 0, 0, 131, 132, 0, 133, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 134, 1, 135, 136, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 137, 138, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, 140, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_indic_positional_category_table_3[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 2, 4, + 2, 3, 3, 3, 3, 1, 1, 1, 1, 2, 2, 2, 2, 3, 4, 2, + 0, 1, 3, 0, 0, 1, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 2, 4, + 2, 3, 3, 3, 3, 0, 0, 4, 4, 0, 0, 5, 5, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 3, 3, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 3, 0, 0, + 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 3, 3, 3, 3, 1, 0, 1, 1, 6, 0, 2, 2, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 2, 1, + 2, 3, 3, 3, 3, 0, 0, 4, 7, 0, 0, 5, 8, 3, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, + 1, 2, 2, 0, 0, 0, 4, 4, 4, 0, 5, 5, 5, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 1, + 1, 2, 2, 2, 2, 0, 1, 1, 9, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 2, 2, 2, 2, 0, 1, 6, 6, 0, 6, 6, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 2, 2, + 2, 3, 3, 3, 3, 0, 4, 4, 4, 0, 5, 5, 5, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, + 2, 2, 1, 1, 3, 0, 3, 0, 2, 4, 7, 4, 5, 8, 5, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 1, 2, 2, 1, 1, 1, 1, 3, 3, 3, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 1, 2, 2, 1, 1, 1, 1, 3, 3, 3, 1, 3, 0, 0, 0, + 10, 10, 10, 10, 10, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 3, 0, 3, 0, 1, 0, 0, 0, 0, 2, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3, 1, 9, 3, 3, 9, 9, 9, 9, 1, 1, 1, 1, 1, 2, + 1, 9, 1, 1, 3, 0, 1, 1, 0, 0, 0, 0, 0, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 1, 1, 3, + 3, 4, 1, 1, 1, 1, 1, 3, 2, 0, 1, 2, 11, 3, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2, 2, 3, 3, 0, 0, 0, 0, 3, 3, + 3, 0, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, + 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 2, 4, 1, 1, 2, 2, 2, 2, 2, 2, 3, 0, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 3, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 3, 3, 3, 7, 8, + 5, 4, 4, 4, 5, 5, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 1, 1, 3, 2, 2, 6, 6, 1, 1, 2, 2, 2, 0, 0, 0, 0, + 2, 2, 3, 2, 2, 2, 2, 2, 2, 3, 1, 3, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 10, 10, 10, 2, 2, 10, 2, 2, 2, 2, 2, + 2, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 3, 4, 2, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 4, 3, 2, 1, 1, 1, 3, 3, 3, 3, 0, + 0, 2, 1, 2, 2, 1, 1, 1, 1, 3, 3, 1, 3, 2, 4, 4, + 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 3, + 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 2, 1, 1, 3, 3, 3, 12, 9, 13, 4, 4, + 5, 5, 1, 6, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2, 3, 3, 1, 3, 4, 2, 1, 1, 2, 0, 3, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 2, 1, 1, 2, 2, 2, 1, 2, 1, + 1, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 2, 2, 4, 4, 7, 2, 2, 3, 1, 1, 1, + 1, 1, 1, 1, 4, 4, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 0, 14, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, + 1, 2, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 3, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2, 2, 3, 1, 2, 0, 0, 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 3, 3, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 1, 3, 3, 3, 3, 1, + 1, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 2, 2, 1, 1, 3, 3, 4, 4, 1, 3, 12, 15, + 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 3, 1, 4, + 4, 1, 3, 2, 4, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 2, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 1, 1, 3, 10, 10, 1, 1, 10, 2, 10, 10, 2, 1, 1, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 3, 1, 4, 2, + 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2, 2, 1, 2, 2, 3, 2, 2, 0, 2, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 14, 3, 3, 0, 1, 14, 0, 0, 0, 0, 0, 3, 3, 3, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 3, 0, 0, 0, 0, 0, + 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 3, 3, 3, 3, + 3, 3, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 4, 2, 3, 3, 1, 1, 2, 2, 3, 3, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 3, 3, 4, 1, 9, 9, + 1, 3, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2, 4, 2, 3, 3, 3, 3, 3, 3, 1, 1, 1, 6, + 2, 0, 1, 1, 0, 0, 0, 0, 0, 3, 3, 1, 3, 0, 4, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 3, + 1, 1, 6, 6, 1, 2, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 2, 4, 2, 3, 3, 1, 1, 1, 1, 3, 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 2, 2, + 1, 2, 2, 2, 2, 0, 0, 4, 4, 0, 0, 5, 5, 2, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2, 2, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 6, 3, 3, 3, 3, 3, + 3, 0, 4, 0, 0, 4, 0, 5, 5, 2, 2, 0, 2, 2, 1, 2, + 0, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2, 4, 2, 3, 3, 3, 3, 3, 3, 1, 1, + 2, 2, 3, 1, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 4, 2, 3, 3, 3, 3, 3, 3, 4, 1, 7, 5, 2, 5, 1, + 1, 2, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, + 4, 2, 3, 3, 3, 3, 0, 0, 4, 7, 5, 8, 1, 1, 2, 3, + 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 3, 3, 3, 3, 3, 3, 1, 1, 2, 2, 1, 2, 3, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 4, 2, + 3, 3, 1, 1, 1, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 11, 1, + 2, 2, 1, 1, 3, 3, 4, 1, 3, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 2, 3, + 3, 3, 3, 1, 1, 1, 1, 1, 2, 3, 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 4, 0, 4, 5, 0, 0, 1, 1, 2, 0, 1, + 2, 1, 12, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2, 4, 2, 3, 3, 3, 3, 0, 0, 1, 1, 2, 2, 2, 2, + 3, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 3, 3, 1, 1, 1, 1, 1, 1, 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 3, 3, 1, 1, 1, 1, 2, 1, 3, 3, 3, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 3, 3, 1, 1, 1, 2, 2, 3, 3, 3, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, + 1, 1, 3, 3, 3, 3, 3, 0, 1, 1, 1, 1, 1, 1, 2, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 0, 2, 3, 3, 3, 3, 3, 3, + 3, 4, 3, 1, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 3, 0, 0, 0, 1, 0, 1, 1, 0, 1, + 1, 1, 3, 1, 3, 0, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, + 1, 1, 0, 2, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 3, 4, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 2, 1, 1, 3, 3, 3, 0, 0, 0, 4, 4, + 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 2, 1, 3, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +RE_UINT32 re_get_indic_positional_category(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = codepoint & 0x1F; + + v = re_indic_positional_category_table_1[field_2]; + v = re_indic_positional_category_table_2[(v << 5) | field_1]; + v = re_indic_positional_category_table_3[(v << 5) | field_0]; + + return v; +} + +/* Indic_Syllabic_Category. */ +static RE_UINT8 re_indic_syllabic_category_table_1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 10, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 11, 1, 12, 13, 14, 15, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 16, 1, 1, 17, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +}; + +static RE_UINT8 re_indic_syllabic_category_table_2[] = { + 0, 1, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 17, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 27, 35, 36, 37, 38, 39, 40, 41, + 42, 43, 44, 0, 45, 46, 47, 0, 0, 48, 49, 50, 51, 52, 53, 0, + 54, 55, 56, 57, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 59, 60, 61, 62, 54, 63, 64, 65, + 0, 0, 0, 0, 0, 0, 0, 0, 66, 67, 68, 69, 54, 70, 71, 0, + 72, 54, 73, 74, 75, 0, 0, 0, 76, 77, 78, 0, 79, 80, 54, 81, + 54, 82, 83, 0, 0, 0, 84, 85, 0, 0, 0, 0, 0, 0, 0, 86, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 87, 0, 0, 88, 89, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 0, 103, 104, 105, 106, + 107, 108, 109, 110, 54, 111, 112, 113, 0, 0, 0, 0, 0, 0, 114, 115, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 116, 117, 118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 119, 120, 121, 122, 123, 124, 125, 0, 126, 127, 128, 129, 130, 131, 132, 133, + 134, 135, 136, 0, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, + 149, 150, 151, 152, 153, 154, 155, 0, 0, 0, 0, 0, 149, 156, 157, 0, + 149, 158, 159, 0, 160, 161, 162, 163, 164, 165, 166, 0, 0, 0, 0, 0, + 160, 167, 0, 0, 0, 0, 0, 0, 168, 169, 170, 0, 0, 171, 172, 173, + 174, 175, 176, 54, 177, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 178, 179, 180, 181, 182, 183, 0, 0, 184, 185, 186, 187, 188, 65, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 189, 190, 191, 192, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 193, 194, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 196, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_indic_syllabic_category_table_3[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 9, 10, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 11, 8, 8, + 0, 12, 12, 0, 0, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, + 6, 6, 8, 8, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 0, 0, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, + 1, 4, 4, 5, 0, 6, 6, 6, 6, 6, 6, 6, 6, 0, 0, 6, + 6, 0, 0, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 7, 7, 7, 7, 7, 7, + 7, 0, 7, 0, 0, 0, 7, 7, 7, 7, 0, 0, 9, 10, 8, 8, + 8, 8, 8, 8, 8, 0, 0, 8, 8, 0, 0, 8, 8, 11, 13, 0, + 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 7, 7, 0, 7, + 6, 6, 8, 8, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 3, 0, + 0, 4, 4, 5, 0, 6, 6, 6, 6, 6, 6, 0, 0, 0, 0, 6, + 6, 0, 0, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 7, 7, 7, 7, 7, 7, + 7, 0, 7, 7, 0, 7, 7, 0, 7, 7, 0, 0, 9, 0, 8, 8, + 8, 8, 8, 0, 0, 0, 0, 8, 8, 0, 0, 8, 8, 11, 0, 0, + 0, 12, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 0, 7, 0, + 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 4, 14, 1, 1, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 4, 4, 5, 0, 6, 6, 6, 6, 6, 6, 6, 6, 6, 0, 6, + 6, 6, 0, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 7, 7, 7, 7, 7, 7, + 7, 0, 7, 7, 0, 7, 7, 7, 7, 7, 0, 0, 9, 10, 8, 8, + 8, 8, 8, 8, 8, 8, 0, 8, 8, 8, 0, 8, 8, 11, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 6, 8, 8, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 12, 14, 12, 9, 9, 9, + 0, 4, 4, 5, 0, 6, 6, 6, 6, 6, 6, 6, 6, 0, 0, 6, + 6, 0, 0, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 0, 0, 8, 8, 0, 0, 8, 8, 11, 0, 0, + 0, 0, 0, 0, 0, 8, 8, 8, 0, 0, 0, 0, 7, 7, 0, 7, + 6, 6, 8, 8, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 16, 0, 6, 6, 6, 6, 6, 6, 0, 0, 0, 6, 6, + 6, 0, 6, 6, 6, 7, 0, 0, 0, 7, 7, 0, 7, 0, 7, 7, + 0, 0, 0, 7, 7, 0, 0, 0, 7, 7, 7, 0, 0, 0, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 8, 8, + 8, 8, 8, 0, 0, 0, 8, 8, 8, 0, 8, 8, 8, 11, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 5, 4, 6, 6, 6, 6, 6, 6, 6, 6, 0, 6, 6, + 6, 0, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 9, 10, 8, 8, + 8, 8, 8, 8, 8, 0, 8, 8, 8, 0, 8, 8, 8, 11, 0, 0, + 0, 0, 0, 0, 0, 8, 8, 0, 7, 7, 7, 0, 0, 13, 0, 0, + 6, 6, 8, 8, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 5, 0, 6, 6, 6, 6, 6, 6, 6, 6, 0, 6, 6, + 6, 0, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 0, 7, 7, 7, 7, 7, 0, 0, 9, 10, 8, 8, + 8, 8, 8, 8, 8, 0, 8, 8, 8, 0, 8, 8, 8, 11, 0, 0, + 0, 0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 0, 0, 13, 7, 0, + 6, 6, 8, 8, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 0, 17, 17, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 18, 18, 10, 8, 8, + 8, 8, 8, 8, 8, 0, 8, 8, 8, 0, 8, 8, 8, 11, 19, 0, + 0, 0, 0, 0, 13, 13, 13, 8, 0, 0, 0, 0, 0, 0, 0, 6, + 6, 6, 8, 8, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, + 0, 4, 4, 5, 0, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 0, 0, 0, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 7, 0, 0, + 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 11, 0, 0, 0, 0, 8, + 8, 8, 8, 8, 8, 0, 8, 0, 8, 8, 8, 8, 8, 8, 8, 8, + 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 0, 0, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 18, 0, 0, 0, 0, 0, + 8, 8, 8, 8, 8, 8, 0, 8, 20, 20, 20, 20, 21, 4, 18, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, + 0, 7, 7, 0, 7, 0, 7, 7, 7, 7, 7, 0, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 0, 7, 0, 7, 7, 7, 7, 7, 7, 7, 7, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 18, 8, 15, 15, 0, 0, + 8, 8, 8, 8, 8, 0, 0, 0, 20, 20, 20, 20, 0, 4, 3, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 7, 7, 7, 7, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 0, 3, 0, 3, 0, 9, 0, 0, 0, 0, 0, 0, + 7, 7, 7, 7, 7, 7, 7, 7, 0, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, + 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 4, 5, + 8, 8, 4, 4, 18, 10, 0, 0, 22, 22, 22, 22, 22, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 0, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 4, 20, 5, 24, 18, 15, 15, 15, 15, 7, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 0, 1, 0, + 7, 7, 6, 6, 6, 6, 8, 8, 8, 8, 7, 7, 7, 7, 15, 15, + 15, 7, 8, 20, 20, 7, 7, 8, 8, 20, 20, 20, 20, 20, 7, 7, + 7, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 15, 8, 8, 8, 8, 20, 20, 20, 20, 20, 20, 20, 7, 20, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 20, 20, 8, 8, 0, 0, + 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 8, 8, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, + 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 8, 8, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 7, 7, + 7, 0, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 4, 5, 8, 25, 25, 3, 26, 21, 3, 3, + 3, 18, 24, 3, 0, 0, 0, 0, 0, 0, 0, 0, 10, 3, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 23, 23, 23, 0, 0, 0, 0, + 27, 27, 4, 27, 27, 27, 27, 27, 27, 27, 8, 3, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 0, 0, + 29, 29, 29, 29, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 27, 27, 27, 27, 27, 27, 27, 20, 20, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 0, 0, 0, 0, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, + 6, 6, 6, 7, 7, 15, 15, 23, 27, 27, 30, 23, 23, 23, 23, 0, + 24, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 4, 20, 20, 20, 20, 20, 18, 3, 3, 0, 0, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 27, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 11, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, + 4, 27, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 23, 23, 23, 8, 8, 8, 8, 8, 8, 18, 24, 23, 23, 7, 7, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 10, 7, 7, 7, 27, 27, + 7, 7, 7, 7, 6, 6, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 27, 27, 31, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 7, 7, 7, 7, 23, 23, 8, 8, 8, 8, 8, 8, 8, 27, 27, 27, + 27, 27, 27, 27, 4, 4, 3, 9, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 7, 7, 7, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 12, 12, 12, 0, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 13, 13, 12, 17, 17, 12, 12, 12, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 33, 0, 0, + 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 6, 8, 6, 6, 6, 11, 7, 7, 7, 7, 4, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 8, 8, 8, 8, 8, 0, 0, 0, 0, 18, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 28, 28, + 28, 28, 7, 7, 7, 7, 28, 23, 23, 7, 7, 7, 7, 7, 7, 7, + 7, 23, 7, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 15, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 11, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 8, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 28, 28, 28, 28, 28, 28, 28, 28, 28, 20, 20, 20, 0, 0, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 27, + 27, 27, 27, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 27, 5, 6, 6, 6, 6, 6, 7, 7, 7, 6, 6, 6, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 15, 15, 15, + 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, + 7, 7, 7, 7, 7, 8, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 7, 7, 7, 7, 7, 0, + 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 0, 7, 7, 7, 1, 1, 1, 0, 0, 0, 7, 20, 20, 20, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 20, + 29, 20, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, + 0, 0, 0, 0, 0, 5, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, + 7, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 27, 27, 27, 27, 27, + 27, 27, 27, 8, 8, 8, 8, 8, 8, 8, 8, 0, 20, 18, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, + 7, 8, 8, 8, 0, 8, 8, 0, 0, 0, 0, 0, 8, 8, 4, 5, + 7, 7, 7, 7, 0, 7, 7, 7, 0, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 0, 0, 9, 9, 9, 0, 0, 0, 0, 24, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 5, 17, 17, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 18, 6, 6, 8, 8, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, + 4, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 11, 9, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 5, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 24, 18, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 0, 0, 0, 0, 7, 8, 8, 7, 0, 0, 0, 0, 0, 0, 0, 0, + 28, 28, 28, 28, 28, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 11, 10, 36, 36, 0, 0, 0, 0, 0, 3, 9, 8, 8, 0, 8, 4, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 4, 11, 9, 14, 0, 0, 0, 0, 0, 0, 12, 7, + 6, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 6, 6, 6, 7, 7, 7, 0, 7, 0, 7, 7, 7, 7, 0, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 4, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 18, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 5, 0, 6, 6, 6, 6, 6, 6, 6, 6, 0, 0, 6, + 6, 0, 0, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 7, 7, 7, 7, 7, 7, + 7, 0, 7, 7, 0, 7, 7, 7, 7, 7, 0, 9, 9, 10, 8, 8, + 8, 8, 8, 8, 8, 0, 0, 8, 8, 0, 0, 8, 8, 11, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 4, 4, + 6, 6, 8, 8, 0, 0, 12, 12, 12, 12, 12, 12, 12, 0, 0, 0, + 12, 12, 12, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 0, 6, 0, 0, 6, 0, + 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 0, 10, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 0, 8, 0, 0, 8, 0, 8, 8, 8, 4, 0, 4, 5, 18, 18, + 24, 19, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 11, 4, 4, 5, 9, 10, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 3, 4, + 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 4, + 4, 5, 11, 9, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, + 8, 8, 8, 8, 8, 8, 0, 0, 8, 8, 8, 8, 4, 4, 5, 11, + 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 8, 8, 0, 0, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 4, 5, 11, + 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 4, 5, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 11, 9, 7, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 15, 15, 15, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 18, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, + 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 4, 5, 11, 9, 0, 0, 0, 0, 0, + 6, 6, 6, 6, 6, 6, 6, 0, 0, 6, 0, 0, 7, 7, 7, 7, + 7, 7, 7, 7, 0, 7, 7, 0, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 0, 8, 8, 0, 0, 4, 4, 18, 24, 36, + 15, 19, 15, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, + 6, 6, 6, 6, 6, 6, 6, 6, 0, 0, 6, 6, 6, 6, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 8, 8, 8, 8, 8, 8, 8, 0, 0, 8, 8, 8, 8, 4, 5, + 11, 10, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 3, 18, 4, 4, 4, 4, 5, 36, 15, 15, 15, 15, 1, + 0, 0, 0, 0, 0, 1, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, + 7, 7, 7, 7, 36, 36, 36, 36, 36, 36, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 4, 5, 14, 24, 0, 0, 0, 10, 0, 0, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 0, 6, 6, 6, 6, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, + 8, 8, 8, 8, 8, 8, 8, 0, 8, 8, 8, 8, 4, 4, 5, 11, + 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, + 0, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 0, 0, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 0, 23, 23, 23, 23, 23, 23, 23, + 8, 8, 8, 8, 8, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 6, 6, 6, 6, 6, 6, 0, 6, 6, 0, 6, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 8, 8, 8, 8, 8, 8, 0, 0, 0, 8, 0, 8, 8, 0, 8, + 4, 5, 9, 8, 18, 24, 19, 15, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, + 6, 6, 6, 6, 6, 6, 0, 6, 6, 0, 6, 6, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 0, + 8, 8, 0, 8, 8, 4, 5, 24, 0, 0, 0, 0, 0, 0, 0, 0, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 1, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 19, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 8, 8, + 8, 18, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 0, 0, 0, 0, 0, + 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 15, 15, 15, 4, 15, 18, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, + 4, 4, 5, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 18, 18, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0 +}; + +RE_UINT32 re_get_indic_syllabic_category(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = codepoint & 0x1F; + + v = re_indic_syllabic_category_table_1[field_2]; + v = re_indic_syllabic_category_table_2[(v << 5) | field_1]; + v = re_indic_syllabic_category_table_3[(v << 5) | field_0]; + + return v; +} + +/* Join_Control. */ +RE_UINT32 re_get_join_control(RE_UINT32 codepoint) { + if (0x200C <= codepoint && codepoint <= 0x200D) + return 1; + + return 0; +} + +/* Joining_Group. */ +static RE_UINT8 re_joining_group_table_1[] = { + 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_joining_group_table_2[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 0, 0, 0, + 0, 0, 0, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 16, 17, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 18, 19, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_joining_group_table_3[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 2, 2, 3, 2, 4, 2, 5, 6, 5, 5, 7, 7, 7, 8, + 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 15, + 0, 16, 17, 18, 19, 20, 21, 22, 3, 4, 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 17, + 0, 2, 2, 2, 0, 2, 3, 3, 4, 5, 5, 5, 5, 5, 5, 5, + 5, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 11, 11, 12, + 13, 16, 16, 16, 16, 16, 16, 17, 17, 14, 23, 14, 18, 18, 18, 14, + 14, 14, 14, 14, 14, 19, 19, 19, 19, 21, 21, 21, 21, 24, 25, 7, + 6, 26, 26, 27, 3, 3, 3, 3, 3, 3, 3, 3, 15, 28, 15, 3, + 4, 4, 29, 29, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 11, 13, 0, 0, 25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 30, 0, 31, 32, 32, 33, 33, 34, 35, 36, 37, 38, 38, 39, 40, 41, + 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 33, 52, 53, 31, 32, 33, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 55, 56, + 5, 5, 5, 5, 5, 5, 5, 7, 7, 8, 8, 9, 10, 13, 13, 13, + 16, 16, 14, 14, 14, 20, 20, 21, 21, 21, 19, 9, 9, 10, 7, 7, + 10, 9, 7, 2, 2, 15, 15, 4, 3, 3, 57, 57, 7, 10, 10, 18, + 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 0, 0, 0, 69, 0, 0, 21, 7, 12, 12, 14, 70, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 7, 12, 16, 17, 19, 20, 4, 4, 9, 3, 71, 0, 8, 11, + 14, 72, 9, 13, 18, 17, 5, 5, 5, 9, 4, 73, 74, 75, 5, 5, + 5, 7, 14, 13, 74, 7, 7, 19, 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 76, 77, 77, 78, 78, 79, 0, 80, 0, 81, 81, 0, 0, 82, 83, 84, + 85, 85, 85, 86, 87, 88, 89, 90, 91, 92, 92, 93, 93, 94, 95, 95, + 95, 96, 0, 0, 97, 0, 0, 0, 0, 0, 0, 98, 99, 100, 101, 102, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 103, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 0, 0, 103, 0, 104, 0, + 104, 0, 0, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 8, 12, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +RE_UINT32 re_get_joining_group(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = codepoint & 0x1F; + + v = re_joining_group_table_1[field_2]; + v = re_joining_group_table_2[(v << 5) | field_1]; + v = re_joining_group_table_3[(v << 5) | field_0]; + + return v; +} + +/* Joining_Type. */ +static RE_UINT8 re_joining_type_table_1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 11, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 12, 13, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 14, 15, + 16, 9, 17, 18, 19, 20, 21, 22, 9, 9, 9, 9, 9, 23, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 24, 9, 25, 26, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 27, + 9, 9, 9, 28, 29, 9, 30, 9, 31, 32, 33, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 34, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 +}; + +static RE_UINT8 re_joining_type_table_2[] = { + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 3, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, + 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 36, 40, 41, 39, 36, 42, 43, 35, 44, 45, 34, 46, 0, 47, 0, + 48, 49, 50, 34, 35, 44, 51, 34, 52, 53, 37, 34, 35, 0, 54, 0, + 0, 55, 56, 0, 0, 57, 58, 0, 59, 60, 0, 61, 62, 63, 64, 0, + 0, 65, 66, 67, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 70, 71, 71, 71, 0, 72, 73, 0, + 74, 13, 13, 75, 76, 77, 0, 0, 0, 78, 0, 0, 0, 0, 0, 0, + 79, 0, 80, 81, 0, 82, 83, 0, 84, 85, 46, 86, 52, 87, 0, 88, + 0, 89, 0, 0, 0, 0, 90, 91, 0, 0, 0, 0, 0, 0, 2, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 92, 93, 0, 94, 0, 0, 82, 95, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 97, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 98, 0, 0, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 100, 101, 0, 0, 102, 0, 0, 0, 0, 0, 0, 0, 0, + 103, 104, 13, 105, 0, 0, 106, 107, 0, 108, 109, 0, 31, 110, 0, 111, + 0, 112, 113, 36, 0, 114, 35, 115, 0, 0, 0, 0, 0, 0, 0, 116, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 117, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 3, 0, 0, 0, 0, 0, 97, 0, 0, 0, 0, 0, 0, 0, 118, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, + 0, 0, 0, 0, 0, 0, 0, 120, 0, 0, 0, 121, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 122, 123, 0, 0, 0, 0, 124, 125, 0, 0, 0, 0, 126, 127, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 128, 129, 0, 130, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 131, 132, 133, 0, 134, 135, 136, 137, 138, 139, 0, + 35, 140, 141, 142, 52, 143, 46, 0, 31, 144, 0, 145, 52, 146, 147, 0, + 0, 148, 35, 0, 0, 0, 97, 149, 52, 53, 120, 150, 0, 151, 152, 39, + 0, 140, 153, 0, 0, 154, 155, 0, 0, 0, 0, 0, 0, 156, 157, 0, + 0, 158, 120, 0, 0, 159, 0, 0, 160, 161, 0, 0, 0, 0, 0, 0, + 0, 162, 0, 0, 0, 0, 0, 0, 0, 163, 164, 0, 0, 0, 165, 120, + 166, 167, 168, 0, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 170, 0, 0, 171, 172, 0, 0, 0, 173, 174, 0, 175, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 176, 52, 121, 177, 0, 0, 0, 0, 0, + 0, 82, 178, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 101, 179, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 180, 0, 181, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 182, 0, 183, 0, 0, 184, + 0, 0, 0, 0, 185, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2, 186, 141, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, 188, 98, 0, 0, + 0, 0, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 190, 2, 191, 192, 193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 194, 195, 0, 0, 182, 0, 0, 0, 0, 181, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 196, 0, 197, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 197, 0, 0, 0, 0, 0, 0, 0, 198, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 181, 0, 13, 13, 199, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 35, 2, 2, 2, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_joining_type_table_3[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, + 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, + 2, 0, 3, 3, 3, 3, 2, 3, 2, 3, 2, 2, 2, 2, 2, 3, + 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 4, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, + 1, 3, 3, 3, 0, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 3, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 3, 2, 3, + 2, 2, 3, 3, 0, 3, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, + 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 3, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 3, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 2, 3, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 3, 2, 3, 2, 2, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 3, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 2, 2, 2, + 2, 3, 2, 3, 3, 2, 2, 2, 3, 3, 2, 2, 2, 2, 2, 2, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 4, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 2, 2, 2, 2, 2, 3, 3, 2, 3, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 3, 2, 3, 3, 3, 1, 1, 1, 0, 0, 0, 0, + 2, 0, 2, 2, 2, 2, 0, 3, 2, 3, 3, 0, 0, 0, 0, 0, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 4, 4, 4, 2, 0, 0, 2, 2, 2, 2, 2, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 0, 3, 2, + 2, 3, 3, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, + 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, + 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, + 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 4, 1, 1, 1, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 4, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, + 2, 2, 2, 2, 2, 3, 0, 3, 0, 3, 3, 0, 0, 5, 3, 3, + 3, 3, 3, 2, 2, 2, 2, 5, 2, 2, 2, 2, 2, 3, 2, 2, + 2, 3, 0, 0, 3, 1, 1, 0, 0, 0, 0, 2, 2, 2, 2, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 3, 2, 3, 3, 3, 2, 2, 2, 3, 2, 2, 3, 2, 3, 3, + 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 2, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 3, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 0, 2, 2, 3, 3, 3, 0, 2, 3, 3, 2, 2, 3, 2, 2, + 0, 2, 3, 3, 2, 0, 0, 0, 0, 3, 2, 5, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, + 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, + 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, + 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +RE_UINT32 re_get_joining_type(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = codepoint & 0x1F; + + v = re_joining_type_table_1[field_2]; + v = re_joining_type_table_2[(v << 5) | field_1]; + v = re_joining_type_table_3[(v << 5) | field_0]; + + return v; +} + +/* Line_Break. */ +static RE_UINT8 re_line_break_table_1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 13, + 13, 13, 13, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 18, 19, 20, 25, 26, 26, 27, 27, 27, 27, 27, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 27, 40, 41, 42, 43, 43, + 44, 45, 27, 27, 27, 27, 27, 27, 46, 27, 47, 48, 13, 13, 13, 13, + 13, 49, 50, 51, 27, 27, 27, 27, 27, 27, 27, 52, 53, 27, 27, 54, + 27, 27, 27, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 67, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 67, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 68, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27 +}; + +static RE_UINT16 re_line_break_table_2[] = { + 0, 1, 2, 3, 4, 5, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 8, 7, 9, 9, 10, 11, 12, 13, 7, 7, + 7, 7, 7, 7, 14, 7, 7, 7, 7, 15, 16, 7, 17, 18, 19, 20, + 21, 7, 22, 23, 7, 7, 24, 25, 26, 27, 28, 7, 7, 29, 30, 31, + 32, 33, 34, 35, 36, 7, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 54, 55, 52, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, + 78, 79, 80, 81, 82, 83, 84, 81, 85, 86, 87, 88, 89, 90, 91, 81, + 92, 92, 93, 92, 94, 7, 95, 7, 96, 96, 96, 97, 97, 98, 99, 99, + 7, 7, 100, 7, 101, 102, 103, 7, 104, 7, 105, 106, 107, 7, 7, 108, + 109, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 110, 7, 7, 111, 112, 113, 114, 115, 92, 92, 116, 117, + 118, 7, 7, 119, 120, 121, 7, 122, 123, 124, 125, 126, 92, 127, 128, 7, + 129, 92, 130, 131, 132, 133, 134, 81, 135, 136, 137, 138, 139, 140, 141, 142, + 7, 143, 144, 145, 35, 146, 147, 148, 7, 7, 7, 7, 7, 7, 149, 150, + 7, 7, 7, 7, 7, 7, 7, 7, 108, 7, 151, 152, 7, 153, 154, 155, + 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 7, 169, 7, + 170, 171, 172, 173, 174, 175, 7, 176, 177, 178, 7, 7, 7, 7, 7, 179, + 7, 180, 181, 182, 182, 182, 182, 183, 182, 182, 184, 185, 186, 187, 188, 189, + 190, 191, 192, 193, 194, 195, 196, 197, 198, 7, 199, 200, 201, 7, 202, 203, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 204, 7, 205, 206, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 207, 208, 209, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 210, 7, 95, 7, 211, 212, 213, 213, 9, + 214, 215, 216, 81, 217, 218, 218, 219, 218, 218, 218, 218, 218, 218, 220, 221, + 222, 223, 224, 225, 226, 227, 225, 228, 229, 230, 218, 218, 231, 218, 218, 232, + 233, 218, 234, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, + 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, + 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, + 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 7, 7, + 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, + 235, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, + 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, + 218, 218, 218, 218, 236, 218, 237, 145, 7, 7, 7, 7, 7, 7, 7, 7, + 238, 239, 7, 240, 241, 7, 7, 242, 7, 7, 7, 7, 7, 7, 243, 244, + 245, 246, 7, 247, 248, 249, 250, 251, 30, 252, 253, 254, 255, 256, 257, 258, + 141, 259, 260, 92, 92, 92, 261, 262, 263, 264, 7, 265, 7, 7, 7, 266, + 267, 268, 269, 270, 271, 272, 273, 267, 268, 269, 270, 271, 272, 273, 267, 268, + 269, 270, 271, 272, 273, 267, 268, 269, 270, 271, 272, 273, 267, 268, 269, 270, + 271, 272, 273, 267, 268, 269, 270, 271, 272, 273, 267, 268, 269, 270, 271, 272, + 273, 267, 268, 269, 270, 271, 272, 273, 267, 268, 269, 270, 271, 272, 273, 267, + 268, 269, 270, 271, 272, 273, 267, 268, 269, 270, 271, 272, 273, 267, 268, 269, + 270, 271, 272, 273, 267, 268, 269, 270, 271, 272, 273, 267, 268, 269, 270, 271, + 272, 273, 267, 268, 269, 270, 271, 272, 273, 267, 268, 269, 270, 271, 272, 273, + 267, 268, 269, 270, 271, 272, 273, 267, 268, 269, 270, 271, 272, 273, 267, 268, + 269, 270, 271, 272, 273, 267, 268, 269, 270, 271, 272, 273, 267, 268, 269, 270, + 271, 272, 273, 267, 268, 269, 270, 271, 272, 273, 267, 268, 269, 270, 271, 272, + 273, 267, 268, 269, 270, 271, 272, 273, 267, 268, 269, 270, 271, 272, 273, 267, + 268, 269, 270, 271, 272, 273, 267, 268, 269, 270, 271, 272, 273, 267, 268, 269, + 270, 271, 272, 273, 267, 268, 269, 270, 271, 272, 273, 267, 268, 269, 270, 271, + 272, 273, 267, 268, 269, 270, 271, 272, 273, 267, 268, 269, 270, 271, 272, 273, + 272, 273, 267, 268, 269, 270, 271, 272, 273, 267, 268, 269, 270, 271, 272, 273, + 267, 268, 269, 270, 271, 272, 273, 267, 268, 269, 270, 271, 272, 274, 275, 276, + 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, + 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 218, 218, 218, 218, 218, 218, 218, 218, + 218, 218, 218, 218, 218, 218, 218, 218, 278, 279, 280, 7, 7, 7, 281, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 282, 7, 7, 283, 7, 284, 285, + 286, 287, 288, 289, 7, 7, 7, 290, 291, 292, 293, 294, 295, 233, 296, 297, + 298, 299, 300, 81, 7, 7, 7, 301, 302, 303, 7, 7, 304, 305, 306, 307, + 81, 81, 81, 81, 308, 7, 309, 310, 7, 311, 35, 312, 313, 7, 314, 81, + 7, 7, 7, 7, 152, 315, 316, 317, 7, 318, 7, 319, 320, 321, 7, 322, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 212, 122, 323, 324, 325, 81, 81, + 326, 327, 328, 7, 123, 329, 81, 330, 331, 332, 81, 81, 7, 333, 283, 7, + 334, 335, 336, 7, 7, 81, 7, 337, 7, 338, 339, 340, 341, 342, 81, 81, + 7, 7, 343, 81, 7, 344, 7, 345, 7, 346, 30, 347, 348, 81, 81, 81, + 81, 81, 81, 123, 7, 349, 350, 351, 7, 318, 352, 306, 353, 306, 354, 212, + 355, 356, 357, 358, 139, 359, 360, 361, 139, 362, 363, 364, 139, 365, 366, 367, + 368, 369, 370, 81, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, + 7, 383, 384, 385, 7, 27, 386, 81, 81, 81, 81, 81, 7, 387, 388, 81, + 7, 27, 389, 390, 7, 391, 392, 393, 394, 395, 396, 81, 81, 81, 81, 81, + 7, 397, 81, 81, 81, 7, 7, 398, 399, 400, 401, 81, 81, 402, 403, 404, + 405, 406, 407, 7, 408, 409, 7, 119, 410, 81, 81, 81, 81, 81, 7, 411, + 412, 413, 414, 415, 416, 417, 81, 81, 418, 419, 420, 421, 422, 423, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 424, 425, 426, 427, 81, 81, 428, 429, 430, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 107, 81, 81, 81, + 7, 7, 7, 431, 7, 7, 7, 7, 7, 7, 432, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 306, 7, 7, 344, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 433, 7, 434, 7, 7, 7, 7, 7, 7, 435, 7, 7, 7, 7, + 7, 436, 437, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 301, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 438, 7, + 7, 7, 439, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 440, 441, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 119, 123, 442, 7, 123, 315, 443, 7, 444, 445, 446, 447, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 7, 448, 81, 81, 81, 81, + 81, 81, 7, 7, 449, 81, 81, 81, 7, 7, 450, 9, 451, 81, 81, 452, + 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, + 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 453, + 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, + 218, 218, 218, 218, 218, 218, 218, 218, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 122, 454, 455, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 456, + 218, 218, 218, 218, 218, 218, 218, 218, 218, 457, 458, 459, 218, 218, 218, 218, + 218, 218, 218, 218, 218, 218, 218, 460, 81, 81, 81, 81, 81, 81, 81, 81, + 7, 7, 7, 461, 462, 463, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 7, 7, 7, 7, 7, 7, 7, 464, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 322, 81, 81, 9, 465, 466, 7, 7, 7, 432, 81, + 7, 7, 7, 7, 7, 7, 7, 122, 7, 467, 7, 468, 469, 470, 7, 181, + 7, 7, 471, 81, 81, 81, 322, 322, 7, 7, 212, 119, 81, 81, 81, 81, + 7, 7, 153, 7, 472, 473, 474, 7, 475, 476, 477, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 478, 7, 7, 7, 7, 7, 7, 7, 7, 479, 480, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 9, 481, 9, 482, 483, 484, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 123, 485, 81, 81, 81, 81, 81, 81, + 486, 487, 7, 488, 489, 81, 81, 81, 7, 490, 491, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 306, 492, 7, 493, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 306, 494, 81, 81, 81, 81, 81, 81, 306, 495, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 496, + 7, 7, 7, 7, 7, 7, 497, 81, 7, 7, 498, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 499, 7, 500, 81, 81, 501, 152, 81, 81, 81, 81, 81, 81, + 474, 502, 503, 504, 505, 506, 81, 507, 81, 81, 81, 81, 81, 81, 81, 81, + 218, 218, 218, 218, 218, 218, 218, 218, 508, 509, 182, 510, 182, 511, 218, 512, + 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 513, 514, 515, 516, + 218, 218, 517, 518, 519, 520, 218, 218, 521, 522, 523, 524, 525, 218, 526, 527, + 218, 218, 528, 529, 218, 530, 531, 218, 7, 7, 7, 532, 7, 7, 533, 218, + 265, 7, 534, 7, 318, 535, 385, 81, 536, 537, 218, 538, 218, 539, 540, 218, + 7, 7, 532, 218, 218, 218, 541, 542, 7, 7, 7, 7, 543, 7, 7, 464, + 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, + 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 544, + 545, 9, 9, 9, 81, 81, 81, 81, 9, 9, 9, 9, 9, 9, 9, 546, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81 +}; + +static RE_UINT8 re_line_break_table_3[] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 4, 4, 5, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 6, 7, 8, 9, 10, 11, 9, 8, 12, 13, 9, 10, 14, 15, 14, 16, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 14, 14, 9, 9, 9, 7, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 12, 10, 13, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 12, 2, 18, 9, 1, + 1, 1, 1, 1, 1, 19, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 20, 12, 11, 10, 10, 10, 9, 21, 21, 9, 21, 8, 9, 2, 9, 9, + 11, 10, 21, 21, 22, 9, 21, 21, 21, 21, 21, 8, 21, 21, 21, 12, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 21, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 21, 22, 21, 21, 21, 22, 21, 9, 9, + 21, 9, 9, 9, 9, 9, 9, 9, 21, 21, 21, 21, 9, 21, 9, 22, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, 20, 20, 20, + 20, 20, 20, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 14, 9, + 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 0, 9, 0, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 14, 2, 0, 0, 9, 9, 10, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, + 9, 1, 1, 9, 1, 1, 7, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 0, 0, 0, 0, 23, + 23, 23, 23, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 17, 17, 17, 17, 17, 17, 9, 9, 9, 11, 11, 11, 14, 14, 9, 9, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 7, 1, 7, 7, 7, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 11, 17, 17, 9, 9, 9, + 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 7, 9, 1, 1, 1, 1, 1, 1, 1, 17, 9, 1, + 1, 1, 1, 1, 1, 9, 9, 1, 1, 9, 1, 1, 1, 1, 9, 9, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, + 9, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 9, 9, 9, 9, 14, 7, 9, 0, 0, 1, 10, 10, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 1, 1, 1, 1, 9, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 9, 1, 1, 1, 9, 1, 1, 1, 1, 1, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 1, 1, 1, 0, 0, 9, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, + 17, 17, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 17, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 1, 1, 1, 9, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 9, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 1, 1, 2, 2, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 1, 1, 1, 0, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, + 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, + 9, 0, 9, 0, 0, 0, 9, 9, 9, 9, 0, 0, 1, 9, 1, 1, + 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 9, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 9, 9, 0, 9, + 9, 9, 1, 1, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 9, 9, 11, 11, 9, 9, 9, 9, 9, 11, 9, 10, 9, 9, 1, 0, + 0, 1, 1, 1, 0, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, + 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, + 9, 0, 9, 9, 0, 9, 9, 0, 9, 9, 0, 0, 1, 0, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 0, 9, 0, + 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 1, 1, 9, 9, 9, 1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, + 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, + 9, 0, 9, 9, 0, 9, 9, 9, 9, 9, 0, 0, 1, 9, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 1, 1, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 9, 10, 0, 0, 0, 0, 0, 0, 0, 9, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 0, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, + 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 9, 9, 0, 9, + 9, 9, 1, 1, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 9, 0, 9, 9, 9, 9, 9, 9, 0, 0, 0, 9, 9, + 9, 0, 9, 9, 9, 9, 0, 0, 0, 9, 9, 0, 9, 0, 9, 9, + 0, 0, 0, 9, 9, 0, 0, 0, 9, 9, 9, 0, 0, 0, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 9, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, + 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 1, 9, 1, 1, + 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 9, 9, 9, 0, 0, 9, 0, 0, + 9, 9, 1, 1, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 0, 0, 0, 0, 0, 0, 0, 22, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 1, 1, 1, 22, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, + 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 0, 0, 1, 9, 1, 1, + 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 9, 9, 0, + 9, 9, 1, 1, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 0, 9, 9, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, + 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 1, 1, 9, 1, 1, + 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 9, 9, + 0, 0, 0, 0, 9, 9, 9, 1, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 1, 1, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 11, 9, 9, 9, 9, 9, 9, + 0, 1, 1, 1, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 1, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 0, 0, 1, 1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 0, 0, 10, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 9, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 2, 2, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 24, 24, 0, 24, 0, 24, 24, 24, 24, 24, 0, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 0, 24, 0, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, + 24, 24, 24, 24, 24, 0, 24, 0, 24, 24, 24, 24, 24, 24, 24, 0, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 24, 24, 24, 24, + 9, 22, 22, 22, 22, 9, 22, 22, 20, 22, 22, 2, 20, 7, 7, 7, + 7, 7, 20, 9, 7, 9, 9, 9, 1, 1, 9, 9, 9, 9, 9, 9, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 2, 1, 9, 1, 9, 1, 12, 18, 12, 18, 1, 1, + 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, + 1, 1, 1, 1, 1, 2, 1, 1, 9, 9, 9, 9, 9, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, + 9, 9, 9, 9, 9, 9, 1, 9, 9, 9, 9, 9, 9, 0, 9, 9, + 22, 22, 2, 22, 9, 9, 9, 9, 9, 20, 20, 0, 0, 0, 0, 0, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 2, 2, 9, 9, 9, 9, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 24, 24, 24, 24, 24, 24, + 9, 9, 9, 9, 9, 9, 0, 9, 0, 0, 0, 0, 0, 9, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 0, 9, 0, 9, 9, 9, 9, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 0, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 0, + 9, 0, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 0, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 1, 1, 1, + 9, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 0, 0, + 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 12, 18, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 2, 2, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 1, 1, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, + 9, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 2, 2, 28, 24, 2, 9, 2, 10, 24, 24, 0, 0, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 9, 9, 7, 7, 2, 2, 22, 9, 7, 7, 9, 1, 1, 1, 20, 1, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 1, 9, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 9, 0, 0, 0, 7, 7, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, + 24, 24, 24, 24, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 0, 0, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 0, 0, 0, 0, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 24, 24, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 1, 1, 1, 1, 1, 0, 0, 9, 9, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 1, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 30, 29, 29, 29, 29, 29, 29, 29, 29, 0, 2, 2, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 2, 2, 32, 2, 2, 2, + 2, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2, 2, 2, + 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 9, 9, 9, 9, 9, 9, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 33, 33, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, + 9, 9, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 2, 2, 2, 2, 2, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 9, 9, 9, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 2, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 1, 9, 9, + 9, 9, 9, 9, 1, 9, 9, 1, 1, 1, 9, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, 1, 1, 1, + 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 0, 9, 0, 9, 0, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 0, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 22, 9, 0, + 2, 2, 2, 2, 2, 2, 2, 20, 2, 2, 2, 34, 1, 35, 1, 1, + 2, 20, 2, 2, 36, 21, 21, 9, 8, 8, 12, 8, 8, 8, 12, 8, + 21, 21, 9, 9, 37, 37, 37, 2, 4, 4, 1, 1, 1, 1, 1, 20, + 11, 11, 11, 11, 11, 11, 11, 11, 9, 8, 8, 21, 28, 28, 9, 9, + 9, 9, 9, 9, 14, 12, 18, 28, 28, 28, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 2, 11, 2, 2, 2, 2, 9, 2, 2, 2, + 38, 9, 9, 9, 9, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 9, 9, 0, 0, 21, 9, 9, 9, 9, 9, 9, 9, 9, 12, 18, 21, + 9, 21, 21, 21, 21, 9, 9, 9, 9, 9, 9, 9, 9, 12, 18, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 11, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 11, 10, 10, 10, 10, 11, 10, 10, 11, 10, + 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 11, 9, 21, 9, 9, 9, 11, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 21, 9, 9, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 21, 21, 9, 9, 9, 9, 9, 9, 9, 9, 21, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 9, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 9, 9, 9, 9, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 21, 9, 9, 0, 0, 0, 0, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 21, 9, 21, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 21, 9, 21, 21, 9, 9, 9, 21, 21, 9, 9, 21, 9, 9, 9, 21, + 9, 21, 10, 10, 9, 21, 9, 9, 9, 9, 21, 9, 9, 21, 21, 21, + 21, 9, 9, 21, 9, 21, 9, 21, 21, 21, 21, 21, 21, 9, 21, 9, + 9, 9, 9, 9, 21, 21, 21, 21, 9, 9, 9, 9, 21, 21, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 21, 9, 9, 9, 21, 9, 9, 9, + 9, 9, 21, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 21, 21, 9, 9, 21, 21, 21, 21, 9, 9, 21, 21, 9, 9, 21, 21, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 21, 21, 9, 9, 21, 21, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 21, 9, 9, 9, 21, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 21, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 21, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 37, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 12, 18, 12, 18, 9, 9, 9, 9, + 9, 9, 21, 9, 9, 9, 9, 9, 9, 9, 32, 32, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 12, 18, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 32, 32, 32, 32, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 9, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 9, 9, 9, 9, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 9, 9, 21, 21, 21, 21, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 21, 21, 9, 21, 21, 21, 21, 21, 21, 21, 9, 9, 9, 9, 9, 9, + 9, 9, 21, 21, 9, 9, 21, 21, 9, 9, 9, 9, 21, 21, 9, 9, + 21, 21, 9, 9, 9, 9, 21, 21, 21, 9, 9, 21, 9, 9, 21, 21, + 21, 21, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 21, 21, 21, 21, 9, 9, 9, 9, 9, 9, 9, 9, 9, 21, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 32, 32, 32, 32, 9, 21, 21, 9, 9, 21, 9, 9, 9, 9, 21, 21, + 9, 9, 9, 9, 32, 32, 21, 21, 32, 9, 32, 32, 32, 39, 32, 32, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 32, 32, 32, 9, 9, 9, 9, + 21, 9, 21, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 21, 21, 9, 21, 21, 21, 9, 21, 32, 21, 21, 9, 21, 21, 9, 21, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 32, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 21, 21, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 21, 21, 21, 21, 32, 9, 32, + 32, 32, 21, 32, 32, 21, 21, 21, 32, 32, 21, 21, 32, 21, 21, 32, + 32, 32, 9, 21, 9, 9, 9, 9, 21, 21, 32, 21, 21, 21, 21, 21, + 21, 32, 32, 32, 32, 32, 21, 32, 32, 39, 32, 21, 21, 32, 32, 32, + 32, 32, 32, 32, 32, 9, 9, 9, 32, 32, 39, 39, 39, 39, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 21, 9, 9, 9, 8, 8, 8, 8, 8, + 8, 9, 7, 7, 32, 9, 9, 9, 12, 18, 12, 18, 12, 18, 12, 18, + 12, 18, 12, 18, 12, 18, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 12, 18, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 12, 18, 12, 18, 12, 18, 12, 18, 12, 18, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 12, 18, 12, 18, 12, 18, 12, 18, 12, 18, 12, 18, 12, + 18, 12, 18, 12, 18, 12, 18, 12, 18, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 12, 18, 12, 18, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 12, 18, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 21, 21, 21, 21, 21, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 1, + 1, 1, 9, 9, 0, 0, 0, 0, 0, 7, 2, 2, 2, 9, 7, 2, + 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 9, + 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 0, + 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2, 2, + 2, 2, 2, 2, 2, 2, 9, 2, 12, 2, 9, 9, 8, 8, 9, 9, + 8, 8, 12, 18, 12, 18, 12, 18, 12, 18, 2, 2, 2, 2, 7, 9, + 2, 2, 9, 2, 2, 9, 9, 9, 9, 9, 36, 36, 2, 2, 2, 9, + 2, 2, 12, 2, 2, 2, 2, 2, 2, 2, 2, 9, 2, 9, 2, 2, + 9, 9, 9, 7, 7, 12, 13, 12, 13, 12, 13, 12, 13, 2, 0, 0, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 2, 18, 18, 32, 32, 28, 32, 32, 12, 18, 12, 18, 12, 18, 12, 18, + 12, 18, 32, 32, 12, 18, 12, 18, 12, 18, 12, 18, 28, 12, 18, 18, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 1, 1, 1, 1, 1, 1, + 32, 32, 32, 32, 32, 1, 32, 32, 32, 32, 32, 28, 28, 32, 32, 32, + 0, 40, 32, 40, 32, 40, 32, 40, 32, 40, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 40, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 40, 32, 40, 32, 40, 32, 32, 32, 32, 32, 32, 40, 32, + 32, 32, 32, 32, 32, 40, 40, 0, 0, 1, 1, 28, 28, 28, 28, 32, + 28, 40, 32, 40, 32, 40, 32, 40, 32, 40, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 40, 32, 40, 32, 40, 32, 32, 32, 32, 32, 32, 40, 32, + 32, 32, 32, 32, 32, 40, 40, 32, 32, 32, 32, 28, 40, 28, 28, 32, + 0, 0, 0, 0, 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, + 32, 32, 32, 32, 32, 32, 32, 32, 21, 21, 21, 21, 21, 21, 21, 21, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 28, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, 0, 0, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 7, 2, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 9, 9, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 1, + 1, 1, 1, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 1, 1, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 1, 1, 9, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, + 9, 9, 0, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 1, 9, 9, 9, 1, 9, 9, 9, 9, 1, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 1, 1, 1, 1, 1, 9, 9, 9, 9, 1, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 11, 9, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 22, 22, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 22, 9, 9, 1, + 9, 9, 9, 9, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, + 1, 1, 1, 1, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 30, 32, 32, 32, 32, 32, 32, 2, 2, 2, 32, 32, 32, 32, 0, 2, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 0, 0, 0, 0, 32, 32, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 24, 24, 24, 24, 24, 0, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 0, 0, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 0, 0, 32, 2, 2, 2, + 24, 24, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 24, 24, 24, 24, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 1, 1, 1, 1, 1, + 2, 2, 9, 9, 9, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 0, + 0, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 0, 0, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, + 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 41, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 41, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 0, 0, 0, 0, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 23, 1, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 9, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 0, 23, 23, 23, 23, 23, 0, 23, 0, + 23, 23, 0, 23, 23, 0, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 12, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 11, 9, 9, 9, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 18, 18, 18, 28, 28, 7, 7, 12, 18, 37, 0, 0, 0, 0, 0, 0, + 20, 1, 20, 1, 20, 1, 20, 20, 1, 20, 1, 20, 1, 20, 20, 1, + 32, 32, 32, 32, 32, 12, 18, 12, 18, 12, 18, 12, 18, 12, 18, 12, + 18, 12, 18, 12, 18, 32, 32, 12, 18, 32, 32, 32, 32, 32, 32, 32, + 18, 32, 18, 0, 28, 28, 7, 7, 32, 12, 18, 12, 18, 12, 18, 32, + 32, 32, 32, 32, 32, 32, 32, 0, 32, 10, 11, 32, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 38, + 0, 7, 32, 32, 10, 11, 32, 32, 12, 18, 32, 32, 18, 32, 18, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 28, 28, 32, 32, 32, 7, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 12, 32, 18, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 12, 32, 18, 32, 12, + 18, 18, 12, 18, 18, 28, 32, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 28, 28, + 0, 0, 32, 32, 32, 32, 32, 32, 0, 0, 32, 32, 32, 32, 32, 32, + 0, 0, 32, 32, 32, 32, 32, 32, 0, 0, 32, 32, 32, 0, 0, 0, + 11, 10, 32, 32, 32, 10, 10, 0, 9, 9, 9, 9, 9, 9, 9, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 44, 21, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 0, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, + 2, 2, 2, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 1, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, + 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 2, + 9, 9, 9, 9, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, + 2, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, + 9, 9, 9, 0, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 0, 0, 9, 0, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 0, 9, 9, 0, 0, 0, 9, 0, 0, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 0, 2, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 0, 9, 9, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 2, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, 9, 9, 9, + 9, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, + 9, 9, 9, 9, 0, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 9, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 1, 1, 0, 0, 0, 0, 9, 9, 9, 9, 9, + 2, 2, 2, 2, 2, 2, 37, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 0, 0, 0, 1, 1, 1, 1, 1, 2, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 1, 1, 2, 0, 0, + 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, + 9, 9, 9, 9, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 9, 9, 1, 1, 1, 1, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 45, 45, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 30, 2, 2, 32, 32, 32, 32, 32, 0, 0, + 0, 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 1, 29, 29, 1, 1, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 17, 2, 2, + 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 2, 2, 2, 2, 9, 1, 1, 9, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 1, 9, 22, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 9, 9, 9, 9, 2, 2, 9, 2, 1, 1, 1, 1, 9, 1, 1, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 9, 22, 9, 2, 2, 2, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 9, 2, 2, 9, 1, 9, + 9, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 0, 9, 0, 9, 9, 9, 9, 0, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 29, 29, 29, 29, 29, 29, 29, 29, 0, 0, 29, + 29, 0, 0, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 0, 29, 29, 29, 29, 29, 29, + 29, 0, 29, 29, 0, 29, 29, 29, 29, 29, 0, 1, 1, 2, 1, 1, + 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 30, 0, 0, + 31, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 31, 31, + 29, 29, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 0, 31, 0, 0, 31, 0, + 31, 31, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 0, 32, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, + 30, 45, 1, 32, 32, 32, 0, 32, 32, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 2, 2, 2, 2, 9, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 2, 2, 0, 9, 1, 9, + 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 1, + 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 22, 2, 2, 7, 7, 9, 9, 9, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 1, 1, 0, 0, + 1, 2, 2, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 0, 0, 0, 0, 0, 0, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 0, 0, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 24, 24, 2, 2, 2, 24, + 24, 24, 24, 24, 24, 24, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 0, 0, 0, 0, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, + 29, 29, 29, 29, 29, 29, 29, 0, 0, 29, 0, 0, 29, 29, 29, 29, + 29, 29, 29, 29, 0, 29, 29, 0, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 30, 45, + 1, 45, 1, 1, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, + 1, 9, 22, 9, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 1, 1, 1, 1, 1, 1, 1, 9, 1, 1, 1, 1, 22, + 9, 2, 2, 2, 2, 22, 9, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 9, 22, 22, + 22, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 9, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, + 22, 7, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 0, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, + 1, 1, 1, 1, 1, 1, 9, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 0, 9, 9, 0, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 1, 1, 1, 1, 1, 0, + 1, 1, 0, 1, 1, 1, 1, 1, 9, 0, 0, 0, 0, 0, 0, 0, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 2, 1, 1, 1, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 45, 1, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 0, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, + 1, 1, 30, 2, 2, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 11, 11, 11, + 11, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, + 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 12, 12, 12, 18, 18, 18, 9, 9, + 9, 9, 18, 9, 9, 9, 12, 18, 12, 18, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 12, 18, 18, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 12, + 20, 20, 20, 20, 20, 20, 20, 12, 18, 20, 20, 20, 12, 18, 12, 18, + 1, 9, 9, 9, 9, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 12, 18, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 0, 0, 0, 0, 0, 0, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 2, 2, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, + 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 2, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 9, 9, 9, 9, 9, + 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 2, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 2, 2, 9, 9, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 1, + 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 28, 28, 28, 28, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 0, + 32, 32, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 40, 40, 40, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 40, 40, 40, 40, 0, 0, 0, 0, 0, 0, 0, 0, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 1, 1, 2, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 1, 1, 1, 1, 1, 9, 9, 9, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 9, 9, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 1, 1, 1, 1, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 1, 1, 1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, + 0, 0, 9, 0, 0, 9, 9, 0, 0, 9, 9, 9, 9, 0, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 0, 9, 9, 9, + 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 0, 0, 9, 9, 9, + 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 0, + 9, 9, 9, 9, 9, 0, 9, 0, 0, 0, 9, 9, 9, 9, 9, 9, + 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, + 9, 9, 9, 9, 9, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 1, 9, 9, 2, 2, 2, 2, 9, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 0, 0, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 1, 1, 1, 1, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 10, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 1, 1, 1, 1, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 1, 1, + 9, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 9, + 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 0, 9, 9, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, + 9, 9, 9, 9, 9, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 1, 1, 1, 1, 1, 1, 1, 9, 0, 0, 0, 0, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 12, 12, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 11, 9, 9, 9, + 11, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 9, 9, 0, 9, 0, 0, 9, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 0, 9, 9, 9, 9, 0, 9, 0, 9, 0, 0, 0, 0, + 0, 0, 9, 0, 0, 0, 0, 9, 0, 9, 0, 9, 0, 9, 9, 9, + 0, 9, 9, 0, 9, 0, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, + 0, 9, 9, 0, 9, 0, 0, 9, 9, 9, 9, 0, 9, 9, 9, 9, + 9, 9, 9, 0, 9, 9, 9, 9, 0, 9, 9, 9, 9, 0, 9, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, + 0, 9, 9, 9, 0, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 9, 9, 9, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 9, 9, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 9, 9, 9, 9, 9, 9, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 9, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 32, 32, 32, 32, 32, 39, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 9, 9, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 9, 9, 32, 32, 32, 32, 32, 9, 32, 32, 32, + 32, 32, 39, 39, 39, 32, 32, 39, 32, 32, 39, 39, 39, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 47, 47, 47, 47, 47, + 32, 32, 39, 39, 32, 32, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 32, 32, 32, 39, 32, 32, 32, + 32, 39, 39, 39, 32, 39, 39, 39, 32, 32, 32, 32, 32, 32, 32, 39, + 32, 39, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 9, 32, 9, 32, 9, 32, 32, 32, 32, 32, 39, 32, 32, 32, 32, 9, + 32, 9, 9, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 9, 9, 9, 9, 9, 9, 9, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 39, 39, 32, 32, 32, 32, 39, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 39, 32, 32, 32, 32, 39, 39, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 9, 9, 9, 9, 9, 9, 9, 9, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 9, 9, 9, 9, 9, 9, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 39, 39, 39, 32, 32, 32, 39, 39, 39, 39, 39, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 8, 8, 8, 28, 28, 28, 9, 9, 9, 9, + 32, 32, 32, 39, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 39, 39, 39, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 39, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 39, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 39, 32, 32, 39, + 32, 32, 32, 32, 32, 32, 32, 32, 39, 39, 39, 39, 39, 39, 39, 39, + 32, 32, 32, 32, 32, 32, 39, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 32, 32, 39, 39, 39, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 39, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 39, 39, 32, 39, 39, 32, 39, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 39, 39, 39, + 32, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 32, 32, + 32, 32, 32, 39, 39, 39, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 32, 32, 32, 32, 32, 32, 32, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +RE_UINT32 re_get_line_break(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = codepoint & 0x1F; + + v = re_line_break_table_1[field_2]; + v = re_line_break_table_2[(v << 5) | field_1]; + v = re_line_break_table_3[(v << 5) | field_0]; + + return v; +} + +/* Logical_Order_Exception. */ +RE_UINT32 re_get_logical_order_exception(RE_UINT32 codepoint) { + if (0x0E40 <= codepoint && codepoint <= 0x0E44) + return 1; + if (0x0EC0 <= codepoint && codepoint <= 0x0EC4) + return 1; + if (0x19B5 <= codepoint && codepoint <= 0x19B7) + return 1; + if (codepoint == 0x19BA) + return 1; + if (0xAAB5 <= codepoint && codepoint <= 0xAAB6) + return 1; + if (codepoint == 0xAAB9) + return 1; + if (0xAABB <= codepoint && codepoint <= 0xAABC) + return 1; + + return 0; +} + +/* Lowercase. */ +static RE_UINT8 re_lowercase_table_1[] = { + 0, 1, 2, 2, 3, 2, 2, 4, 5, 6, 2, 7, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 8, 9, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 10, 11, + 2, 12, 2, 13, 2, 2, 14, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 15, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 16, 2, 17, 18, 2, 19, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 +}; + +static RE_UINT8 re_lowercase_table_2[] = { + 0, 0, 0, 1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 5, 13, 14, 15, 16, 17, 18, 19, 0, 0, 20, 21, 22, 23, 24, 25, + 0, 26, 15, 5, 27, 5, 28, 5, 5, 29, 0, 15, 30, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 26, 31, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, + 0, 0, 0, 0, 33, 0, 0, 0, 15, 15, 15, 15, 15, 15, 0, 0, + 5, 5, 5, 5, 34, 5, 5, 5, 35, 36, 37, 38, 36, 39, 40, 41, + 0, 0, 0, 42, 43, 0, 0, 0, 44, 45, 46, 26, 47, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 26, 48, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 26, 15, 49, 5, 5, 5, 50, 15, 51, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 52, 53, 0, 0, 0, 0, 54, 5, 55, 56, 57, 58, 59, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 31, 60, 15, 15, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 61, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 62, 63, 0, 0, 0, 64, 65, 0, 0, 0, 0, 66, 67, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 69, 0, 0, + 0, 0, 0, 0, 0, 0, 15, 70, 0, 0, 0, 26, 71, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 72, 73, 85, + 75, 76, 86, 63, 79, 71, 87, 88, 89, 86, 90, 26, 91, 79, 92, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 93, 94, 0, 0, 0, 0, 0, 0, + 0, 26, 15, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 97, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_lowercase_table_3[] = { + 0, 0, 0, 0, 254, 255, 255, 7, 0, 4, 32, 4, 0, 0, 0, 128, + 255, 255, 127, 255, 170, 170, 170, 170, 170, 170, 170, 85, 85, 171, 170, 170, + 170, 170, 170, 212, 41, 49, 36, 78, 42, 45, 81, 230, 64, 82, 85, 181, + 170, 170, 41, 170, 170, 170, 250, 147, 133, 170, 255, 255, 255, 255, 255, 255, + 255, 255, 239, 255, 255, 255, 255, 1, 3, 0, 0, 0, 31, 0, 0, 0, + 32, 0, 0, 0, 0, 0, 138, 60, 0, 0, 1, 0, 0, 240, 255, 255, + 255, 127, 227, 170, 170, 170, 47, 25, 0, 0, 255, 255, 2, 168, 170, 170, + 84, 213, 170, 170, 170, 170, 0, 0, 255, 1, 0, 0, 255, 255, 255, 247, + 0, 0, 0, 63, 255, 5, 0, 0, 170, 170, 234, 191, 255, 0, 63, 0, + 255, 0, 255, 0, 63, 0, 255, 0, 255, 0, 255, 63, 255, 0, 223, 64, + 220, 0, 207, 0, 255, 0, 220, 0, 0, 0, 2, 128, 0, 0, 255, 31, + 0, 196, 8, 0, 0, 128, 16, 50, 192, 67, 0, 0, 16, 0, 0, 0, + 255, 3, 0, 0, 98, 21, 218, 63, 26, 80, 8, 0, 191, 32, 0, 0, + 170, 42, 0, 0, 170, 170, 170, 58, 168, 170, 171, 170, 170, 170, 255, 149, + 170, 80, 186, 170, 170, 130, 160, 170, 10, 37, 170, 10, 0, 0, 92, 7, + 255, 3, 255, 255, 127, 0, 248, 0, 0, 255, 255, 255, 255, 255, 0, 0, + 0, 0, 0, 255, 255, 255, 255, 15, 0, 0, 128, 255, 251, 255, 251, 27, + 185, 255, 255, 255, 255, 255, 253, 7, 255, 255, 7, 0, 63, 0, 0, 0, + 0, 0, 0, 252, 255, 255, 15, 0, 0, 192, 223, 255, 255, 0, 0, 0, + 252, 255, 255, 15, 0, 0, 192, 235, 239, 255, 0, 0, 0, 252, 255, 255, + 15, 0, 0, 192, 255, 255, 255, 0, 0, 0, 252, 255, 255, 15, 0, 0, + 192, 255, 255, 255, 0, 192, 255, 255, 0, 0, 192, 255, 252, 255, 255, 247, + 3, 0, 0, 240, 255, 255, 223, 15, 255, 127, 63, 0, 255, 253, 0, 0, + 247, 11, 0, 0, 255, 251, 255, 127, 224, 7, 0, 0, 255, 63, 0, 0, + 252, 255, 255, 255, 15, 0, 0, 0 +}; + +RE_UINT32 re_get_lowercase(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_lowercase_table_1[field_2]; + v = re_lowercase_table_2[(v << 5) | field_1]; + v = re_lowercase_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Math. */ +static RE_UINT8 re_math_table_1[] = { + 0, 1, 2, 2, 2, 2, 2, 2, 3, 4, 5, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 7, + 2, 2, 2, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 10, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 +}; + +static RE_UINT8 re_math_table_2[] = { + 0, 1, 2, 3, 0, 4, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 10, 11, 12, 13, 0, 14, 15, 16, 17, 18, 0, 19, 20, 21, 22, + 23, 23, 23, 23, 23, 23, 23, 23, 24, 25, 0, 26, 27, 28, 29, 30, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 32, 33, + 34, 0, 35, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 23, + 0, 0, 0, 0, 0, 0, 0, 0, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 0, 19, 37, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 39, 0, 0, 0, 0, 1, 3, 3, 0, 0, 0, 0, 40, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 23, 23, 42, 23, 43, 44, 45, 23, 46, 47, 48, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 49, 23, 23, 23, 23, 23, 23, 23, 23, 50, 23, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 45, 51, 52, 53, 54, 55, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_math_table_3[] = { + 0, 0, 0, 0, 0, 8, 0, 112, 0, 0, 0, 64, 0, 0, 0, 80, + 0, 16, 2, 0, 0, 0, 128, 0, 0, 0, 39, 0, 0, 0, 115, 0, + 192, 1, 0, 0, 0, 0, 64, 0, 0, 0, 28, 0, 17, 0, 4, 0, + 30, 0, 0, 124, 0, 124, 0, 0, 0, 0, 255, 31, 98, 248, 0, 0, + 132, 252, 47, 63, 16, 179, 251, 241, 255, 11, 0, 0, 0, 0, 255, 255, + 255, 126, 195, 240, 255, 255, 255, 47, 48, 0, 240, 255, 255, 255, 255, 255, + 0, 15, 0, 0, 3, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 248, + 255, 255, 191, 0, 0, 0, 1, 240, 7, 0, 0, 0, 3, 192, 255, 240, + 195, 140, 15, 0, 148, 31, 0, 255, 96, 0, 0, 0, 5, 0, 0, 0, + 15, 224, 0, 0, 159, 31, 0, 0, 0, 2, 0, 0, 126, 1, 0, 0, + 4, 30, 0, 0, 0, 192, 0, 0, 255, 255, 223, 255, 255, 255, 255, 223, + 100, 222, 255, 235, 239, 255, 255, 255, 191, 231, 223, 223, 255, 255, 255, 123, + 95, 252, 253, 255, 63, 255, 255, 255, 255, 207, 255, 255, 150, 254, 247, 10, + 132, 234, 150, 170, 150, 247, 247, 94, 255, 251, 255, 15, 238, 251, 255, 15, + 0, 0, 3, 0 +}; + +RE_UINT32 re_get_math(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_math_table_1[field_2]; + v = re_math_table_2[(v << 5) | field_1]; + v = re_math_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Modifier_Combining_Mark. */ +static RE_UINT8 re_modifier_combining_mark_table_1[] = { + 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_modifier_combining_mark_table_2[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_modifier_combining_mark_table_3[] = { + 0, 0, 0, 0, 0, 0, 48, 1, 0, 0, 0, 16, 136, 1, 0, 0, + 0, 236, 8, 0, 0, 0, 8, 0 +}; + +RE_UINT32 re_get_modifier_combining_mark(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_modifier_combining_mark_table_1[field_2]; + v = re_modifier_combining_mark_table_2[(v << 5) | field_1]; + v = re_modifier_combining_mark_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* NFC_Quick_Check. */ +static RE_UINT8 re_nfc_quick_check_table_1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 5, 9, 5, 10, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 11, 5, + 5, 5, 5, 5, 12, 13, 14, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 15, 5, 5, 16, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 17, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 18, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 +}; + +static RE_UINT8 re_nfc_quick_check_table_2[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 8, 0, 0, 9, 10, 0, + 0, 11, 12, 0, 0, 0, 0, 0, 0, 9, 13, 0, 0, 9, 14, 0, + 0, 0, 15, 0, 0, 0, 16, 0, 0, 9, 14, 0, 0, 0, 17, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 19, 20, 21, 0, 0, + 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 0, 24, 25, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 0, 28, 29, 30, + 31, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 36, 36, 36, 36, 36, 36, 36, 36, + 37, 38, 36, 39, 36, 36, 40, 0, 41, 42, 43, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 44, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 14, 0, 0, 46, 47, 0, + 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 49, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 51, 52, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 55, 0, 56, 57, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_nfc_quick_check_table_3[] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, + 1, 2, 1, 2, 2, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, + 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 1, + 2, 2, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 2, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 0, 0, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, + 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, + 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, + 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, + 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, + 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, + 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, + 1, 1, 2, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 +}; + +RE_UINT32 re_get_nfc_quick_check(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = codepoint & 0x1F; + + v = re_nfc_quick_check_table_1[field_2]; + v = re_nfc_quick_check_table_2[(v << 5) | field_1]; + v = re_nfc_quick_check_table_3[(v << 5) | field_0]; + + return v; +} + +/* NFD_Quick_Check. */ +static RE_UINT8 re_nfd_quick_check_table_1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 5, 9, 5, 10, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 12, 5, 5, 5, 5, 5, 5, 5, 5, 13, 5, + 5, 14, 5, 5, 15, 16, 17, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 18, 5, 5, 19, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 20, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 21, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 +}; + +static RE_UINT8 re_nfd_quick_check_table_2[] = { + 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 0, 7, 8, 9, + 10, 11, 0, 0, 0, 0, 0, 0, 0, 0, 12, 13, 14, 15, 16, 0, + 17, 18, 19, 20, 0, 0, 21, 22, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 23, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 26, 0, 0, 0, 27, 0, + 0, 28, 29, 0, 0, 0, 0, 0, 0, 0, 30, 0, 31, 0, 32, 0, + 0, 0, 33, 0, 0, 0, 34, 0, 0, 0, 32, 0, 0, 0, 35, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 37, 38, 39, 0, 0, + 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 41, 42, 43, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 44, 44, 44, 44, 45, 44, 44, 46, 47, 44, 48, 49, 44, 50, 51, 52, + 53, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 55, 56, 57, 0, + 58, 59, 60, 61, 62, 63, 0, 64, 0, 65, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 67, 68, 13, 67, 68, 69, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 70, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 44, 44, 44, 44, 44, 44, 44, 44, + 71, 72, 44, 73, 44, 44, 46, 0, 74, 75, 76, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 78, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 79, 80, 0, 0, 0, 81, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 0, 83, 0, 84, 0, + 0, 0, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 90, 0, 91, 92, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, + 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_nfd_quick_check_table_3[] = { + 255, 255, 255, 255, 64, 0, 129, 193, 64, 0, 129, 65, 0, 0, 3, 0, + 192, 0, 14, 129, 7, 14, 12, 0, 192, 0, 0, 128, 252, 127, 254, 255, + 255, 31, 0, 32, 48, 0, 206, 0, 0, 0, 0, 48, 63, 0, 240, 255, + 228, 255, 255, 255, 255, 255, 239, 191, 31, 40, 254, 255, 255, 3, 254, 255, + 255, 131, 231, 255, 116, 143, 255, 253, 255, 255, 255, 253, 255, 255, 116, 143, + 255, 255, 63, 255, 249, 255, 48, 3, 3, 3, 192, 252, 131, 255, 255, 255, + 250, 255, 247, 255, 255, 253, 237, 255, 255, 255, 255, 0, 255, 231, 255, 79, + 255, 255, 183, 255, 255, 255, 255, 177, 255, 230, 255, 207, 255, 255, 239, 255, + 255, 227, 255, 255, 255, 254, 255, 255, 126, 242, 255, 255, 255, 255, 255, 139, + 247, 223, 123, 239, 255, 253, 151, 254, 253, 255, 247, 223, 123, 239, 255, 253, + 191, 255, 255, 255, 191, 170, 251, 255, 255, 255, 255, 215, 244, 255, 255, 255, + 0, 0, 0, 0, 0, 0, 0, 244, 0, 0, 0, 252, 0, 0, 192, 192, + 192, 192, 0, 85, 0, 0, 0, 192, 0, 0, 32, 160, 33, 0, 48, 16, + 0, 0, 35, 192, 252, 255, 255, 255, 191, 243, 255, 255, 255, 255, 255, 243, + 255, 191, 255, 255, 255, 31, 255, 255, 239, 237, 255, 255, 175, 255, 255, 255, + 109, 253, 255, 255, 250, 31, 204, 252, 204, 252, 255, 255, 255, 15, 255, 255, + 240, 195, 255, 255, 255, 249, 255, 255, 255, 255, 255, 239, 255, 175, 170, 170, + 90, 253, 36, 201, 255, 255, 111, 184, 240, 255, 255, 255, 0, 192, 26, 128, + 154, 3, 0, 0, 0, 192, 0, 0, 255, 255, 255, 95, 255, 3, 128, 160, + 36, 128, 255, 255, 255, 253, 255, 255, 239, 255, 255, 255, 255, 255, 255, 235, + 255, 247, 255, 255, 255, 63, 255, 255, 255, 231, 255, 255, 215, 191, 253, 255, + 95, 254, 255, 255, 255, 255, 255, 167, 255, 255, 255, 254, 1, 254, 255, 255, + 255, 248, 255, 255, 255, 255, 255, 63, 224, 255, 255, 255, 255, 255, 255, 7, + 254, 255, 255, 255 +}; + +RE_UINT32 re_get_nfd_quick_check(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_nfd_quick_check_table_1[field_2]; + v = re_nfd_quick_check_table_2[(v << 5) | field_1]; + v = re_nfd_quick_check_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* NFKC_Quick_Check. */ +static RE_UINT8 re_nfkc_quick_check_table_1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 13, 14, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 15, 16, + 5, 17, 5, 5, 18, 19, 20, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 21, 5, 5, 22, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 23, 24, 25, 5, 5, 26, 5, 5, 27, 28, 5, 29, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 30, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 +}; + +static RE_UINT8 re_nfkc_quick_check_table_2[] = { + 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 3, 4, 0, 0, 5, 6, + 0, 0, 0, 0, 0, 7, 8, 9, 10, 11, 12, 13, 14, 0, 15, 16, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, + 0, 0, 18, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 21, 0, 0, 22, 23, 0, + 0, 24, 25, 0, 0, 0, 0, 0, 0, 22, 26, 0, 0, 22, 27, 0, + 0, 0, 28, 0, 0, 0, 29, 0, 0, 22, 27, 0, 0, 0, 30, 0, + 0, 31, 0, 0, 0, 31, 32, 0, 33, 0, 34, 35, 36, 37, 0, 0, + 0, 38, 0, 0, 0, 0, 0, 39, 0, 0, 0, 40, 0, 41, 42, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 45, 46, 47, 48, 0, 0, + 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 50, 0, 51, 52, 53, + 54, 55, 56, 57, 58, 59, 0, 0, 60, 61, 62, 48, 63, 0, 0, 0, + 0, 64, 0, 0, 0, 0, 0, 0, 0, 65, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 48, 48, 48, 48, 66, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 33, 0, 0, 67, 0, 0, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 0, 0, 31, 48, 48, 48, 48, 48, 48, 69, 0, + 70, 71, 0, 0, 72, 0, 0, 4, 0, 73, 48, 48, 74, 0, 0, 0, + 75, 48, 76, 75, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 77, 0, 0, 0, 78, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, + 80, 81, 48, 82, 48, 48, 83, 0, 84, 85, 86, 48, 48, 87, 88, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 89, 90, 48, 91, 48, 92, 93, + 94, 90, 95, 96, 48, 48, 48, 97, 98, 48, 48, 48, 48, 75, 99, 100, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 102, 0, 0, + 0, 0, 0, 0, 0, 103, 0, 0, 0, 104, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 27, 0, 0, 105, 106, 0, + 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, 108, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 110, 111, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 113, 83, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 9, 0, 47, 70, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 48, 48, 115, 48, 116, 117, 118, 48, 119, 120, 121, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 122, 48, 48, 48, 48, 48, 48, 48, 48, 123, 48, + 0, 90, 48, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 118, 125, 126, 127, 128, 129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 130, 131, 132, 133, 77, 0, 0, 0, + 134, 135, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 89, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_nfkc_quick_check_table_3[] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, + 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, + 1, 2, 1, 2, 2, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, + 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 1, + 2, 2, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 2, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, + 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 0, 0, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, + 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, + 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, + 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, + 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, + 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, + 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, + 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, + 1, 1, 2, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, + 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, + 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, + 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +}; + +RE_UINT32 re_get_nfkc_quick_check(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = codepoint & 0x1F; + + v = re_nfkc_quick_check_table_1[field_2]; + v = re_nfkc_quick_check_table_2[(v << 5) | field_1]; + v = re_nfkc_quick_check_table_3[(v << 5) | field_0]; + + return v; +} + +/* NFKD_Quick_Check. */ +static RE_UINT8 re_nfkd_quick_check_table_1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 13, 14, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 16, 5, 5, 5, 5, 5, 5, 5, 5, 17, 18, + 5, 19, 5, 5, 20, 21, 22, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 23, 5, 5, 24, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 25, 26, 27, 5, 5, 28, 5, 5, 29, 30, 5, 31, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 32, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 +}; + +static RE_UINT8 re_nfkd_quick_check_table_2[] = { + 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 0, 8, 9, 10, + 11, 12, 0, 0, 0, 13, 14, 15, 0, 0, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 0, 0, 26, 27, 0, 0, 0, 0, 28, 0, 0, 0, + 0, 29, 0, 30, 0, 0, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 33, 0, 0, 0, 34, 0, + 0, 35, 36, 0, 0, 0, 0, 0, 0, 0, 37, 0, 38, 0, 39, 0, + 0, 0, 40, 0, 0, 0, 41, 0, 0, 0, 39, 0, 0, 0, 42, 0, + 0, 43, 0, 0, 0, 43, 44, 0, 45, 0, 46, 47, 48, 49, 0, 0, + 0, 50, 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 52, 53, 54, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 56, 57, 58, 59, 0, 0, + 59, 59, 59, 59, 60, 59, 59, 61, 62, 59, 63, 64, 59, 65, 66, 67, + 68, 69, 70, 71, 72, 40, 0, 0, 73, 74, 75, 59, 76, 77, 78, 0, + 79, 80, 81, 82, 83, 84, 0, 85, 0, 86, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 59, 59, 59, 59, 87, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 45, 0, 0, 88, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 44, 0, 0, 0, 0, 0, 0, 0, 89, 0, 0, 0, 0, + 0, 0, 0, 0, 90, 0, 0, 43, 59, 59, 59, 59, 59, 59, 91, 0, + 92, 93, 94, 95, 96, 94, 95, 97, 0, 98, 59, 59, 99, 0, 0, 0, + 100, 59, 101, 100, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 44, 0, 0, 0, 0, 0, 0, 102, 0, 0, 0, 103, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 105, 0, 0, 0, 0, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 106, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 59, 59, 59, 59, 59, 59, 59, 59, + 107, 108, 59, 109, 59, 59, 61, 0, 110, 111, 112, 59, 59, 113, 114, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 64, 115, 59, 4, 59, 116, 117, + 118, 115, 119, 120, 59, 59, 59, 121, 122, 59, 59, 59, 59, 100, 123, 124, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 125, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 127, 0, 0, + 0, 0, 0, 0, 128, 129, 0, 0, 0, 130, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131, 0, 132, 0, 133, 0, + 0, 0, 0, 0, 0, 134, 0, 0, 0, 0, 0, 0, 0, 135, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 137, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 139, 61, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 15, 0, 58, 92, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 59, 59, 65, 59, 141, 142, 143, 59, 144, 145, 146, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 7, 59, 59, 59, 59, 59, 59, 59, 59, 147, 59, + 0, 115, 59, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 143, 149, 150, 151, 152, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 154, 155, 156, 39, 102, 0, 0, 0, + 157, 60, 158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_nfkd_quick_check_table_3[] = { + 255, 255, 255, 255, 254, 122, 195, 136, 64, 0, 129, 193, 64, 0, 129, 65, + 0, 0, 3, 0, 192, 0, 2, 1, 6, 12, 12, 0, 192, 0, 0, 0, + 252, 127, 254, 255, 15, 0, 0, 32, 48, 0, 192, 0, 0, 0, 0, 48, + 63, 0, 240, 255, 255, 255, 0, 254, 255, 255, 255, 192, 224, 255, 255, 255, + 228, 255, 255, 255, 255, 255, 239, 187, 15, 40, 254, 255, 255, 3, 254, 255, + 255, 131, 128, 255, 255, 255, 200, 253, 116, 143, 255, 253, 255, 255, 255, 253, + 255, 255, 116, 143, 255, 255, 63, 255, 249, 255, 48, 3, 3, 3, 192, 252, + 127, 255, 255, 255, 131, 255, 255, 255, 255, 255, 31, 254, 250, 255, 247, 255, + 255, 253, 237, 255, 255, 255, 255, 0, 255, 231, 255, 79, 255, 255, 183, 255, + 255, 255, 255, 177, 255, 230, 255, 207, 255, 255, 239, 255, 255, 227, 255, 255, + 255, 254, 255, 255, 126, 242, 255, 255, 255, 255, 255, 139, 255, 255, 247, 255, + 255, 255, 255, 207, 255, 239, 255, 255, 247, 223, 123, 239, 255, 253, 23, 252, + 253, 255, 247, 223, 123, 239, 255, 253, 191, 255, 255, 255, 255, 255, 255, 239, + 191, 170, 251, 255, 255, 255, 255, 215, 244, 255, 255, 255, 255, 143, 0, 8, + 0, 64, 0, 0, 0, 248, 255, 254, 255, 255, 255, 7, 0, 0, 0, 0, + 0, 0, 0, 240, 0, 0, 0, 252, 0, 0, 192, 192, 192, 192, 0, 85, + 0, 0, 0, 192, 0, 0, 32, 0, 32, 0, 48, 16, 0, 0, 35, 128, + 0, 248, 125, 255, 143, 127, 39, 175, 127, 252, 127, 127, 255, 255, 12, 0, + 0, 128, 0, 224, 16, 1, 144, 193, 168, 66, 4, 4, 30, 252, 0, 0, + 255, 253, 255, 243, 255, 191, 255, 255, 255, 31, 255, 255, 239, 237, 255, 255, + 175, 79, 254, 255, 109, 253, 255, 255, 250, 31, 204, 252, 204, 252, 255, 255, + 255, 15, 255, 255, 240, 195, 255, 255, 255, 249, 255, 255, 0, 248, 255, 255, + 255, 255, 143, 255, 255, 127, 255, 255, 255, 255, 255, 127, 0, 0, 192, 255, + 254, 255, 255, 255, 255, 255, 191, 248, 255, 175, 170, 170, 90, 253, 36, 201, + 255, 255, 239, 39, 255, 255, 111, 56, 255, 255, 1, 0, 0, 128, 3, 0, + 0, 0, 0, 128, 0, 255, 0, 0, 255, 255, 254, 255, 255, 255, 227, 252, + 255, 255, 255, 15, 255, 253, 255, 255, 240, 255, 255, 255, 0, 192, 26, 128, + 154, 3, 0, 0, 0, 192, 0, 0, 128, 255, 7, 95, 0, 0, 128, 160, + 36, 0, 0, 0, 0, 0, 252, 255, 255, 255, 7, 0, 255, 255, 0, 0, + 0, 255, 255, 255, 255, 255, 0, 224, 255, 255, 0, 252, 96, 0, 8, 0, + 128, 240, 40, 0, 0, 0, 0, 224, 1, 0, 0, 0, 3, 3, 3, 227, + 128, 128, 255, 255, 239, 255, 255, 255, 65, 0, 0, 0, 0, 0, 2, 248, + 255, 255, 255, 235, 255, 247, 255, 255, 255, 63, 255, 255, 255, 231, 255, 255, + 215, 191, 253, 255, 95, 254, 255, 255, 255, 255, 255, 167, 255, 255, 255, 243, + 255, 255, 255, 254, 1, 254, 255, 255, 255, 248, 255, 255, 255, 255, 63, 0, + 255, 255, 255, 63, 0, 0, 0, 32, 155, 33, 0, 20, 16, 0, 0, 0, + 64, 24, 32, 32, 0, 0, 0, 132, 160, 3, 2, 0, 0, 48, 0, 0, + 0, 192, 255, 255, 105, 1, 8, 245, 123, 21, 105, 85, 105, 8, 8, 161, + 0, 4, 0, 240, 17, 4, 0, 240, 0, 248, 0, 0, 0, 128, 0, 0, + 0, 0, 255, 255, 248, 255, 0, 0, 0, 254, 252, 255 +}; + +RE_UINT32 re_get_nfkd_quick_check(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_nfkd_quick_check_table_1[field_2]; + v = re_nfkd_quick_check_table_2[(v << 5) | field_1]; + v = re_nfkd_quick_check_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Noncharacter_Code_Point. */ +static RE_UINT8 re_noncharacter_code_point_table_1[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 +}; + +static RE_UINT8 re_noncharacter_code_point_table_2[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3 +}; + +static RE_UINT8 re_noncharacter_code_point_table_3[] = { + 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 192 +}; + +RE_UINT32 re_get_noncharacter_code_point(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_noncharacter_code_point_table_1[field_2]; + v = re_noncharacter_code_point_table_2[(v << 5) | field_1]; + v = re_noncharacter_code_point_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Numeric_Type. */ +static RE_UINT8 re_numeric_type_table_1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 10, + 10, 10, 10, 15, 16, 17, 18, 19, 20, 21, 10, 22, 23, 24, 25, 10, + 26, 27, 10, 28, 29, 30, 10, 10, 10, 31, 32, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 10, 43, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 44, 10, 45, 46, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 47, 48, 49, 10, 10, 50, 51, 52, 53, 54, 10, 55, 10, + 56, 10, 57, 10, 10, 10, 10, 10, 58, 10, 59, 10, 10, 10, 60, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 61, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 62, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 +}; + +static RE_UINT8 re_numeric_type_table_2[] = { + 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 5, + 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 6, 0, 0, 0, 7, + 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 9, 10, 0, 0, 0, 4, + 0, 0, 1, 0, 0, 0, 1, 0, 0, 11, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 14, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 15, 0, + 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 17, 18, 0, 0, 0, 0, 0, 19, 20, 21, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 22, 23, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 26, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 28, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 0, 0, + 0, 31, 32, 0, 31, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 34, 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 38, 39, 27, 0, 40, 41, 42, 43, 37, 0, 0, 44, 0, 0, 0, 45, + 46, 0, 0, 0, 0, 0, 0, 0, 39, 0, 46, 47, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 0, 0, 49, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 52, 0, 0, 0, 53, 54, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 44, 55, 0, 0, 56, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 46, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 55, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 60, 0, 0, 0, 44, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 62, 63, 64, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3, 0, 0, 0, 0, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 66, 0, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 0, 1, 1, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 57, 68, 27, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 69, 70, 20, 71, 72, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 73, 0, 74, 75, 0, 0, 0, 76, 0, + 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 77, 78, 0, 79, 0, 80, 81, 0, 0, 0, 0, 82, 83, 20, + 0, 0, 84, 85, 86, 0, 0, 87, 0, 0, 77, 77, 0, 88, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 89, 0, 1, 3, 0, 0, 0, 0, 0, + 0, 0, 0, 90, 0, 0, 0, 0, 86, 91, 92, 0, 0, 0, 93, 0, + 0, 0, 94, 95, 0, 0, 0, 1, 0, 96, 0, 0, 0, 0, 1, 97, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 98, 99, 0, 100, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 101, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 102, 103, 0, 0, 0, 0, 0, 0, 1, 0, 0, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 104, 0, + 20, 20, 20, 105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 3, 0, 0, 3, 0, 0, 0, 106, 107, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 70, 70, 0, 0, 0, 71, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 110, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 111, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 79, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 33, 20, 112, 0, 0, 113, 114, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 115, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 62, 0, 0, 39, 0, 0, 0, 116, 0, 62, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 117, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 118, 119, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_numeric_type_table_3[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, 0, 0, 3, 3, 3, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, + 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 0, 0, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, + 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 0, 0, 3, 0, 0, 0, 3, 0, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, + 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3, 0, 3, 3, 3, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 0, + 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, + 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, + 0, 0, 0, 3, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, + 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, + 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, + 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 3, 3, 3, 3, 3, + 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, + 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0 +}; + +RE_UINT32 re_get_numeric_type(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = codepoint & 0x1F; + + v = re_numeric_type_table_1[field_2]; + v = re_numeric_type_table_2[(v << 5) | field_1]; + v = re_numeric_type_table_3[(v << 5) | field_0]; + + return v; +} + +/* Numeric_Value. */ +static RE_UINT8 re_numeric_value_table_1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 10, + 10, 10, 10, 15, 16, 17, 18, 19, 20, 21, 10, 22, 23, 24, 25, 10, + 26, 27, 10, 28, 29, 30, 10, 10, 10, 31, 32, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 10, 43, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 44, 10, 45, 46, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 47, 48, 49, 10, 10, 50, 51, 52, 53, 54, 10, 55, 10, + 56, 10, 57, 10, 10, 10, 10, 10, 58, 10, 59, 10, 10, 10, 60, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 61, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 62, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 +}; + +static RE_UINT8 re_numeric_value_table_2[] = { + 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 5, + 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 6, 0, 0, 0, 7, + 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 9, 10, 0, 0, 0, 4, + 0, 0, 1, 0, 0, 0, 1, 0, 0, 11, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 14, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 15, 0, + 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 16, 3, 0, 0, 0, 0, 0, 17, 18, 19, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 20, 21, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 24, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 26, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, + 0, 29, 30, 0, 29, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 32, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 36, 37, 38, 0, 39, 40, 41, 42, 43, 0, 0, 44, 0, 0, 0, 45, + 46, 0, 0, 0, 0, 0, 0, 0, 47, 0, 48, 49, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 0, 0, 0, 51, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 53, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 54, 0, 0, 0, 55, 56, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 57, 58, 0, 0, 59, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 61, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 64, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 69, 0, 0, 0, 70, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 73, 74, 75, 0, 0, 0, 76, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3, 0, 0, 0, 0, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 78, 0, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 0, 1, 1, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 0, 80, 81, 82, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 83, 84, 85, 86, 87, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 88, 0, 89, 90, 0, 0, 0, 91, 0, + 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 92, 93, 0, 94, 0, 95, 96, 0, 0, 0, 0, 97, 98, 99, + 0, 0, 100, 101, 102, 0, 0, 103, 0, 0, 104, 104, 0, 105, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 106, 0, 1, 3, 0, 0, 0, 0, 0, + 0, 0, 0, 107, 0, 0, 0, 0, 108, 109, 110, 0, 0, 0, 111, 0, + 0, 0, 112, 113, 0, 0, 0, 1, 0, 114, 0, 0, 0, 0, 1, 115, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 116, 117, 0, 118, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 119, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 120, 121, 0, 0, 0, 0, 0, 0, 1, 0, 0, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 122, 0, + 123, 124, 125, 126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 3, 0, 0, 3, 0, 0, 0, 127, 128, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 130, 130, 0, 0, 0, 131, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 133, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 134, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 135, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 136, 137, 138, 0, 0, 139, 140, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 141, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 142, 0, 0, 143, 0, 0, 0, 144, 0, 145, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 146, 0, 0, 147, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 148, 149, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 151, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_numeric_value_table_3[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 4, 0, 0, 0, 0, 0, 2, 0, 0, 11, 12, 13, 0, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 0, 0, 0, 0, 14, 15, 16, 11, 13, 17, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 0, 0, 11, 12, 13, 14, 15, 16, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 18, 19, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 2, 3, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 21, 22, 23, 24, 25, 26, 27, 0, + 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 18, 19, 20, 11, 12, 13, 14, 15, 16, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 18, 37, 38, 39, 40, 41, 42, 43, 44, 19, 45, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 47, + 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0, 0, 0, 0, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 5, 6, 7, 8, 9, 10, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 49, 50, 25, 51, 52, 27, 53, 54, 55, 56, 57, 15, 58, 59, 60, 2, + 2, 3, 4, 5, 6, 7, 8, 9, 10, 18, 61, 62, 40, 19, 63, 20, + 2, 3, 4, 5, 6, 7, 8, 9, 10, 18, 61, 62, 40, 19, 63, 20, + 20, 64, 45, 0, 0, 7, 40, 65, 66, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 3, 4, 5, 6, 7, 8, 9, 10, 18, 61, 62, 67, 68, 69, 17, + 46, 47, 48, 37, 2, 3, 4, 5, 6, 7, 8, 9, 10, 18, 61, 62, + 67, 68, 69, 17, 46, 47, 48, 37, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 18, 61, 62, 67, 68, 69, 17, 46, 47, 48, 37, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 61, 62, 67, 68, 69, + 17, 46, 47, 48, 37, 2, 3, 4, 5, 6, 7, 8, 9, 10, 18, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 18, + 2, 3, 4, 5, 6, 7, 8, 9, 10, 18, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 18, 37, 38, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 3, 4, 5, 6, 7, 8, 9, 10, 18, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 18, 37, 38, 39, 40, 41, 42, 43, + 0, 70, 71, 72, 73, 74, 75, 76, 77, 78, 38, 79, 80, 81, 82, 83, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 84, 85, 86, 87, 39, 88, 89, 90, 91, 92, 93, 94, 95, 96, 40, + 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 0, 0, 8, 0, 0, 0, 45, 0, 4, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 6, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, + 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, + 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 9, 0, 7, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 18, 0, 20, 37, 38, 0, 0, 0, 0, 0, 0, 39, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 37, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 4, 0, + 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, + 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 19, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 12, 13, 14, 15, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, + 0, 0, 0, 18, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 18, 37, 38, 39, 40, 41, 42, 43, 44, 19, 100, 102, 103, 63, 104, 105, + 106, 107, 20, 108, 109, 110, 64, 111, 112, 113, 114, 45, 115, 116, 117, 65, + 118, 119, 120, 121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 12, 2, 6, 40, 63, 64, 65, 6, 18, 40, 19, 63, 20, 64, 6, + 18, 40, 19, 63, 20, 45, 65, 18, 2, 2, 2, 3, 3, 3, 3, 6, + 18, 18, 18, 18, 18, 38, 40, 40, 40, 40, 19, 102, 63, 63, 63, 63, + 63, 20, 64, 6, 40, 12, 12, 52, 13, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 11, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 18, 37, 38, 39, 40, 41, + 42, 43, 44, 19, 100, 102, 103, 63, 104, 105, 106, 107, 0, 0, 0, 0, + 2, 6, 18, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 44, 0, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2, 3, 18, 37, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 4, 18, 37, 19, 20, 45, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 4, 5, 6, 18, 37, + 0, 0, 0, 0, 0, 0, 0, 2, 3, 4, 5, 5, 6, 18, 37, 19, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 18, 37, 19, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2, 18, 37, 19, 3, 4, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 12, 0, 0, + 2, 3, 4, 5, 6, 7, 8, 9, 10, 18, 37, 38, 39, 40, 41, 42, + 0, 0, 19, 100, 102, 103, 63, 104, 105, 106, 107, 20, 108, 109, 110, 64, + 111, 112, 113, 114, 45, 115, 116, 117, 65, 118, 119, 120, 121, 66, 123, 124, + 125, 126, 127, 128, 129, 130, 131, 56, 11, 51, 132, 12, 133, 52, 13, 57, + 2, 3, 4, 5, 18, 37, 19, 20, 12, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 40, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 18, 37, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 18, 37, 19, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 4, 5, 18, 37, 19, 20, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 4, 5, 18, 37, 19, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 18, 40, 19, 20, + 2, 3, 4, 5, 6, 7, 8, 9, 10, 18, 37, 38, 39, 40, 41, 42, + 43, 44, 19, 100, 102, 103, 63, 104, 105, 106, 107, 12, 11, 51, 52, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 4, + 5, 6, 18, 37, 38, 19, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2, 18, 37, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2, 3, 4, 5, 18, 37, 19, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 18, 37, 38, 39, 40, + 41, 42, 43, 44, 19, 20, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 18, 37, 38, 39, 40, 41, + 42, 43, 44, 19, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0, 0, 0, 0, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 18, 37, 0, 0, 0, 0, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 18, 37, 38, 39, 40, 41, + 42, 43, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 18, 37, 38, 39, 40, 41, 42, 43, 44, 19, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 134, 21, 135, 136, 22, 137, 23, 138, 24, 14, 14, 25, 15, 26, 16, 27, + 11, 12, 12, 13, 134, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 4, 5, 6, 7, 8, 9, 10, 4, 5, 6, 7, 8, 9, 10, 5, + 6, 7, 8, 9, 10, 2, 3, 4, 5, 6, 7, 8, 9, 10, 2, 3, + 4, 5, 6, 3, 4, 4, 5, 6, 7, 8, 9, 10, 2, 3, 4, 4, + 5, 6, 139, 140, 2, 3, 4, 4, 5, 6, 4, 4, 5, 5, 5, 5, + 7, 8, 8, 8, 9, 9, 10, 10, 10, 10, 3, 4, 5, 6, 7, 2, + 3, 4, 5, 5, 6, 6, 3, 4, 2, 3, 51, 52, 57, 51, 52, 15, + 11, 56, 11, 11, 12, 51, 52, 39, 40, 5, 6, 7, 8, 9, 10, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 18, 19, 45, 99, 98, + 141, 142, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 18, 61, 62, 67, 68, 69, + 17, 46, 47, 48, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 18, 61, 62, 67, 68, 69, + 17, 46, 47, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 3, 4, 5, 6, 7, 8, 9, 10, 18, 37, 38, 39, 40, 41, 42, + 43, 44, 2, 3, 4, 5, 6, 2, 6, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, + 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 18, 37, 38, 39, 40, 41, + 42, 43, 44, 19, 100, 102, 103, 63, 104, 105, 106, 107, 20, 108, 109, 110, + 64, 111, 112, 113, 114, 45, 115, 116, 117, 65, 118, 119, 120, 121, 66, 123, + 66, 143, 144, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 11, 12, 13, + 0, 2, 3, 45, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 18, 37, 38, 39, 40, 41, + 42, 43, 44, 19, 100, 102, 103, 63, 104, 105, 106, 107, 20, 108, 109, 110, + 64, 111, 112, 113, 114, 45, 115, 116, 117, 65, 118, 119, 120, 121, 0, 3, + 4, 5, 6, 7, 8, 9, 10, 18, 103, 104, 108, 45, 12, 56, 0, 0, + 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 39, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +RE_UINT32 re_get_numeric_value(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = codepoint & 0x1F; + + v = re_numeric_value_table_1[field_2]; + v = re_numeric_value_table_2[(v << 5) | field_1]; + v = re_numeric_value_table_3[(v << 5) | field_0]; + + return v; +} + +/* Other_Alphabetic. */ +static RE_UINT8 re_other_alphabetic_table_1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 10, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 11, 12, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 13, 8, + 14, 8, 15, 16, 17, 18, 19, 20, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 21, 8, 8, 22, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 23, + 8, 8, 8, 8, 8, 8, 8, 8, 24, 8, 25, 8, 26, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 +}; + +static RE_UINT8 re_other_alphabetic_table_2[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 0, + 5, 0, 6, 7, 0, 0, 8, 9, 10, 11, 0, 0, 0, 12, 0, 0, + 13, 14, 0, 0, 15, 0, 16, 17, 18, 19, 20, 21, 22, 23, 24, 21, + 22, 23, 25, 26, 22, 23, 27, 28, 22, 23, 29, 21, 30, 23, 31, 0, + 32, 23, 33, 21, 22, 23, 33, 34, 18, 23, 35, 21, 22, 0, 36, 37, + 0, 38, 39, 0, 0, 40, 39, 0, 0, 0, 0, 41, 42, 43, 0, 0, + 0, 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 37, 37, 37, 37, 0, 48, 49, 0, + 0, 0, 0, 0, 50, 51, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, + 53, 0, 54, 55, 0, 56, 57, 0, 32, 58, 18, 0, 59, 60, 0, 61, + 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 64, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 48, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 67, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 68, 69, 0, 0, 70, 16, 71, 56, 0, 72, 73, 0, 18, 16, 0, 1, + 0, 74, 75, 76, 0, 77, 0, 78, 0, 0, 0, 0, 0, 0, 0, 79, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 0, 51, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 84, 0, 85, 0, 0, 0, 0, 0, 0, 0, 0, + 59, 86, 87, 88, 59, 89, 30, 0, 59, 73, 50, 0, 59, 63, 90, 0, + 0, 91, 92, 0, 0, 0, 56, 49, 18, 23, 24, 21, 0, 86, 93, 0, + 0, 58, 94, 0, 0, 11, 70, 0, 0, 0, 0, 0, 0, 95, 96, 0, + 0, 97, 98, 0, 0, 99, 0, 0, 100, 101, 0, 0, 0, 0, 0, 0, + 0, 102, 0, 0, 0, 0, 0, 0, 0, 103, 104, 0, 0, 0, 105, 106, + 107, 108, 109, 0, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 111, 0, 0, 112, 113, 0, 0, 0, 114, 115, 0, 116, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 117, 118, 119, 98, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 23, 120, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 65, 122, 0, 0, 123, + 0, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 124, 125, 0, 0, 126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 128, 128, 66, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_other_alphabetic_table_3[] = { + 0, 0, 0, 0, 32, 0, 0, 0, 248, 255, 0, 0, 0, 0, 255, 191, + 182, 0, 0, 0, 0, 0, 255, 7, 0, 248, 255, 254, 0, 0, 1, 0, + 0, 0, 192, 31, 158, 33, 0, 0, 0, 0, 2, 0, 0, 0, 255, 255, + 192, 255, 1, 0, 0, 0, 192, 248, 239, 30, 0, 0, 0, 0, 128, 0, + 0, 0, 240, 255, 248, 3, 255, 255, 15, 0, 0, 0, 0, 0, 0, 204, + 255, 223, 224, 0, 12, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 192, + 159, 25, 128, 0, 135, 25, 2, 0, 0, 0, 35, 0, 191, 27, 0, 0, + 12, 0, 0, 28, 159, 25, 192, 0, 4, 0, 0, 0, 199, 29, 128, 0, + 31, 0, 0, 0, 223, 29, 96, 0, 12, 0, 8, 0, 223, 29, 128, 0, + 0, 128, 95, 255, 0, 0, 12, 0, 0, 0, 242, 7, 0, 32, 0, 0, + 0, 0, 242, 27, 0, 0, 254, 255, 15, 224, 255, 254, 255, 255, 255, 31, + 0, 248, 127, 121, 0, 0, 192, 195, 157, 63, 30, 0, 252, 191, 0, 60, + 0, 0, 192, 255, 255, 1, 0, 0, 96, 0, 0, 0, 0, 2, 0, 0, + 255, 15, 255, 1, 0, 0, 128, 15, 0, 0, 224, 127, 254, 255, 31, 0, + 0, 0, 0, 128, 1, 112, 0, 0, 0, 0, 224, 255, 7, 0, 0, 0, + 254, 51, 0, 0, 128, 255, 3, 0, 240, 255, 127, 0, 0, 0, 248, 255, + 255, 255, 31, 0, 255, 255, 255, 255, 255, 3, 0, 0, 0, 0, 240, 15, + 4, 8, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 47, 0, 0, 0, + 192, 7, 0, 0, 128, 255, 7, 0, 0, 254, 127, 0, 8, 48, 0, 0, + 0, 0, 0, 56, 0, 0, 157, 65, 0, 248, 32, 0, 248, 7, 0, 0, + 0, 0, 0, 64, 0, 0, 192, 7, 110, 240, 0, 0, 240, 0, 0, 0, + 0, 24, 0, 0, 0, 0, 0, 16, 0, 0, 0, 255, 63, 0, 0, 0, + 0, 0, 24, 0, 0, 0, 255, 1, 0, 192, 0, 0, 0, 240, 159, 64, + 2, 0, 0, 0, 165, 55, 0, 0, 59, 0, 0, 0, 0, 128, 63, 127, + 0, 0, 0, 48, 0, 0, 255, 127, 1, 0, 0, 0, 0, 248, 63, 0, + 0, 0, 0, 224, 255, 7, 0, 0, 0, 240, 255, 1, 0, 0, 191, 25, + 5, 0, 0, 0, 0, 0, 254, 252, 16, 0, 0, 0, 254, 7, 0, 0, + 0, 0, 224, 123, 0, 0, 254, 15, 0, 252, 255, 0, 0, 128, 127, 127, + 0, 0, 252, 255, 255, 254, 127, 0, 0, 0, 126, 180, 139, 0, 0, 0, + 0, 124, 123, 0, 0, 0, 120, 0, 11, 0, 0, 0, 0, 0, 240, 199, + 255, 127, 0, 0, 0, 128, 254, 255, 255, 128, 7, 0, 0, 0, 3, 0, + 127, 255, 255, 249, 219, 7, 0, 0, 0, 128, 0, 0, 128, 0, 0, 0, + 255, 3, 255, 255 +}; + +RE_UINT32 re_get_other_alphabetic(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_other_alphabetic_table_1[field_2]; + v = re_other_alphabetic_table_2[(v << 5) | field_1]; + v = re_other_alphabetic_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Other_Default_Ignorable_Code_Point. */ +static RE_UINT8 re_other_default_ignorable_code_point_table_1[] = { + 0, 1, 1, 1, 2, 3, 1, 1, 4, 1, 1, 1, 5, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 7, 8, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +}; + +static RE_UINT8 re_other_default_ignorable_code_point_table_2[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, + 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 7, + 8, 0, 0, 0, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 10, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 +}; + +static RE_UINT8 re_other_default_ignorable_code_point_table_3[] = { + 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 128, 1, 0, 0, 0, + 0, 0, 48, 0, 32, 0, 0, 0, 16, 0, 0, 0, 0, 0, 255, 1, + 253, 255, 255, 255, 255, 255, 255, 255, 0, 0, 255, 255 +}; + +RE_UINT32 re_get_other_default_ignorable_code_point(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_other_default_ignorable_code_point_table_1[field_2]; + v = re_other_default_ignorable_code_point_table_2[(v << 5) | field_1]; + v = re_other_default_ignorable_code_point_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Other_Grapheme_Extend. */ +static RE_UINT8 re_other_grapheme_extend_table_1[] = { + 0, 0, 1, 2, 0, 3, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, + 0, 0, 0, 0, 9, 10, 11, 12, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_other_grapheme_extend_table_2[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 1, 2, 0, + 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 2, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 8, 0, 0, 9, 0, 10, + 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 14, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, + 0, 5, 0, 0, 0, 0, 0, 0, 0, 1, 16, 0, 0, 17, 18, 0, + 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, + 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 25, 25, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_other_grapheme_extend_table_3[] = { + 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 128, 0, 133, 13, 96, 0, + 0, 128, 0, 128, 0, 0, 32, 0, 0, 0, 16, 0, 0, 0, 32, 40, + 24, 0, 0, 0, 0, 4, 0, 0, 0, 0, 12, 0, 0, 16, 0, 0, + 0, 192, 0, 0, 0, 0, 8, 0, 1, 0, 0, 0, 0, 0, 0, 192, + 0, 32, 128, 0, 0, 0, 0, 1, 164, 131, 0, 0, 0, 0, 1, 32, + 0, 128, 0, 0, 0, 0, 64, 0, 2, 0, 0, 0, 0, 0, 3, 0, + 96, 224, 7, 0, 255, 255, 255, 255 +}; + +RE_UINT32 re_get_other_grapheme_extend(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_other_grapheme_extend_table_1[field_2]; + v = re_other_grapheme_extend_table_2[(v << 5) | field_1]; + v = re_other_grapheme_extend_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Other_ID_Continue. */ +RE_UINT32 re_get_other_id_continue(RE_UINT32 codepoint) { + if (codepoint == 0xB7) + return 1; + if (codepoint == 0x0387) + return 1; + if (0x1369 <= codepoint && codepoint <= 0x1371) + return 1; + if (codepoint == 0x19DA) + return 1; + if (0x200C <= codepoint && codepoint <= 0x200D) + return 1; + if (codepoint == 0x30FB) + return 1; + if (codepoint == 0xFF65) + return 1; + + return 0; +} + +/* Other_ID_Start. */ +RE_UINT32 re_get_other_id_start(RE_UINT32 codepoint) { + if (0x1885 <= codepoint && codepoint <= 0x1886) + return 1; + if (codepoint == 0x2118) + return 1; + if (codepoint == 0x212E) + return 1; + if (0x309B <= codepoint && codepoint <= 0x309C) + return 1; + + return 0; +} + +/* Other_Lowercase. */ +static RE_UINT8 re_other_lowercase_table_1[] = { + 0, 1, 1, 1, 2, 1, 1, 3, 4, 5, 1, 6, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 7, 8, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 10, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +}; + +static RE_UINT8 re_other_lowercase_table_2[] = { + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2, 3, 4, 0, 0, 5, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 9, 10, 11, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 12, 13, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 18, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 20, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 22, 0, 0, + 0, 14, 9, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_other_lowercase_table_3[] = { + 0, 0, 0, 0, 0, 4, 0, 4, 0, 0, 255, 1, 3, 0, 0, 0, + 31, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 16, + 0, 240, 255, 255, 255, 255, 255, 255, 255, 7, 0, 1, 0, 0, 0, 248, + 0, 0, 2, 128, 0, 0, 255, 31, 0, 0, 255, 255, 255, 3, 0, 0, + 0, 0, 0, 48, 0, 0, 1, 0, 0, 0, 28, 3, 0, 0, 0, 240, + 0, 2, 0, 0, 185, 255, 255, 255, 255, 255, 253, 7, 255, 63, 0, 0 +}; + +RE_UINT32 re_get_other_lowercase(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_other_lowercase_table_1[field_2]; + v = re_other_lowercase_table_2[(v << 5) | field_1]; + v = re_other_lowercase_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Other_Math. */ +static RE_UINT8 re_other_math_table_1[] = { + 0, 1, 1, 1, 1, 1, 1, 1, 2, 3, 4, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 6, 1, 1, 1, 1, 1, 7, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +}; + +static RE_UINT8 re_other_math_table_2[] = { + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 5, 6, 7, 8, 0, 9, 10, 11, 12, 13, 0, 14, 15, 16, 17, + 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 19, 20, 21, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 23, 24, + 25, 0, 26, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 28, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 30, 31, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 32, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, + 34, 34, 35, 34, 36, 37, 38, 34, 39, 40, 41, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 42, 43, 44, 35, 35, 45, 45, 46, 46, 47, 34, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 38, 48, 49, 50, 51, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_other_math_table_3[] = { + 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 39, 0, 0, 0, 51, 0, + 0, 0, 64, 0, 0, 0, 28, 0, 1, 0, 0, 0, 30, 0, 0, 96, + 0, 96, 0, 0, 0, 0, 255, 31, 98, 248, 0, 0, 132, 252, 47, 62, + 16, 179, 251, 241, 224, 3, 0, 0, 0, 0, 224, 243, 182, 62, 195, 240, + 255, 63, 235, 47, 48, 0, 0, 0, 0, 15, 0, 0, 0, 0, 176, 0, + 0, 0, 1, 0, 4, 0, 0, 0, 3, 192, 127, 240, 193, 140, 15, 0, + 148, 31, 0, 0, 96, 0, 0, 0, 5, 0, 0, 0, 15, 96, 0, 0, + 192, 255, 0, 0, 248, 255, 255, 1, 0, 0, 0, 15, 0, 0, 0, 48, + 10, 1, 0, 0, 0, 0, 0, 80, 255, 255, 255, 255, 255, 255, 223, 255, + 255, 255, 255, 223, 100, 222, 255, 235, 239, 255, 255, 255, 191, 231, 223, 223, + 255, 255, 255, 123, 95, 252, 253, 255, 63, 255, 255, 255, 253, 255, 255, 247, + 255, 255, 255, 247, 255, 127, 255, 255, 255, 253, 255, 255, 247, 207, 255, 255, + 150, 254, 247, 10, 132, 234, 150, 170, 150, 247, 247, 94, 255, 251, 255, 15, + 238, 251, 255, 15 +}; + +RE_UINT32 re_get_other_math(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_other_math_table_1[field_2]; + v = re_other_math_table_2[(v << 5) | field_1]; + v = re_other_math_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Other_Uppercase. */ +RE_UINT32 re_get_other_uppercase(RE_UINT32 codepoint) { + if (0x2160 <= codepoint && codepoint <= 0x216F) + return 1; + if (0x24B6 <= codepoint && codepoint <= 0x24CF) + return 1; + if (0x01F130 <= codepoint && codepoint <= 0x01F149) + return 1; + if (0x01F150 <= codepoint && codepoint <= 0x01F169) + return 1; + if (0x01F170 <= codepoint && codepoint <= 0x01F189) + return 1; + + return 0; +} + +/* Pattern_Syntax. */ +static RE_UINT8 re_pattern_syntax_table_1[] = { + 0, 1, 1, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 7, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +}; + +static RE_UINT8 re_pattern_syntax_table_2[] = { + 0, 1, 2, 2, 0, 3, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 10, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, + 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_pattern_syntax_table_3[] = { + 0, 0, 0, 0, 254, 255, 0, 252, 1, 0, 0, 120, 254, 90, 67, 136, + 0, 0, 128, 0, 0, 0, 255, 255, 255, 0, 255, 127, 254, 255, 239, 127, + 255, 255, 255, 255, 255, 255, 63, 0, 0, 0, 240, 255, 14, 255, 255, 255, + 1, 0, 1, 0, 0, 0, 0, 192, 96, 0, 0, 0 +}; + +RE_UINT32 re_get_pattern_syntax(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_pattern_syntax_table_1[field_2]; + v = re_pattern_syntax_table_2[(v << 5) | field_1]; + v = re_pattern_syntax_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Pattern_White_Space. */ +RE_UINT32 re_get_pattern_white_space(RE_UINT32 codepoint) { + if (0x09 <= codepoint && codepoint <= 0x0D) + return 1; + if (codepoint == 0x20) + return 1; + if (codepoint == 0x85) + return 1; + if (0x200E <= codepoint && codepoint <= 0x200F) + return 1; + if (0x2028 <= codepoint && codepoint <= 0x2029) + return 1; + + return 0; +} + +/* Posix_AlNum. */ +static RE_UINT8 re_posix_alnum_table_1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 13, + 13, 13, 13, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 15, 16, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 17, 10, 10, 10, 10, 10, 10, 10, 10, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 10, 30, 13, 31, 13, 13, + 32, 33, 10, 10, 10, 10, 10, 10, 34, 10, 35, 36, 13, 13, 13, 13, + 13, 37, 13, 38, 10, 10, 10, 10, 10, 10, 10, 39, 40, 10, 10, 41, + 10, 10, 10, 10, 10, 42, 10, 43, 44, 45, 46, 47, 48, 10, 10, 10, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 49, 13, 13, 13, 50, 51, 13, + 13, 13, 13, 52, 13, 13, 13, 13, 13, 13, 53, 54, 10, 10, 55, 10, + 13, 13, 13, 13, 56, 13, 13, 13, 57, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 +}; + +static RE_UINT16 re_posix_alnum_table_2[] = { + 0, 1, 2, 2, 0, 3, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 6, 7, 0, 0, 8, 9, 10, 11, 5, 12, + 5, 5, 5, 5, 13, 5, 5, 5, 5, 14, 15, 5, 16, 17, 18, 19, + 20, 5, 21, 22, 5, 5, 23, 24, 25, 5, 26, 5, 5, 27, 28, 29, + 30, 31, 32, 33, 34, 5, 35, 36, 5, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 49, 53, 54, 55, 56, 57, 0, + 58, 59, 60, 61, 62, 63, 64, 65, 58, 66, 67, 68, 69, 70, 71, 72, + 73, 74, 75, 0, 76, 77, 78, 0, 79, 0, 80, 81, 82, 83, 0, 0, + 5, 84, 25, 5, 85, 5, 86, 87, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 88, 5, 89, 90, 91, 5, 92, 5, 74, 0, 93, 5, 5, 94, + 73, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 95, 2, 5, 5, 96, 97, 98, 98, 99, 5, 100, 101, 0, + 0, 5, 5, 32, 5, 33, 5, 102, 103, 104, 25, 105, 5, 106, 107, 0, + 108, 5, 103, 109, 0, 110, 111, 0, 5, 112, 113, 0, 5, 114, 5, 115, + 5, 116, 117, 118, 33, 66, 0, 119, 5, 5, 5, 5, 5, 5, 120, 121, + 5, 5, 5, 5, 5, 5, 5, 5, 94, 5, 122, 118, 5, 123, 124, 125, + 0, 0, 0, 126, 127, 0, 0, 0, 128, 129, 130, 5, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 131, 5, 107, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 132, 5, 86, 5, 133, 116, 134, 134, 5, + 0, 135, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 136, 137, 73, 5, 138, 73, 5, 87, 139, 14, 5, 5, 140, 5, 0, 25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 31, 0, 25, 118, 5, 5, 5, 5, 5, 5, 5, 5, + 141, 142, 5, 143, 5, 5, 5, 93, 144, 145, 5, 5, 146, 5, 147, 148, + 149, 150, 5, 98, 5, 5, 151, 152, 28, 33, 153, 83, 5, 154, 135, 155, + 5, 116, 156, 157, 5, 103, 158, 159, 160, 161, 87, 162, 5, 5, 5, 163, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 164, 165, 108, + 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 166, 5, 5, 167, 0, 168, 169, 170, 5, 5, 27, 120, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 118, 25, 5, 171, 5, 150, 172, + 0, 0, 0, 173, 5, 5, 5, 83, 0, 2, 2, 174, 5, 103, 175, 0, + 176, 177, 178, 0, 5, 5, 5, 74, 0, 0, 5, 121, 0, 0, 0, 0, + 0, 0, 0, 0, 83, 5, 179, 0, 5, 26, 33, 74, 118, 5, 180, 0, + 5, 5, 5, 5, 118, 25, 181, 108, 5, 182, 5, 183, 184, 185, 5, 98, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 116, 102, 150, 149, 186, 0, 0, + 187, 188, 102, 116, 103, 0, 0, 189, 102, 167, 0, 0, 5, 190, 0, 0, + 191, 102, 0, 83, 83, 0, 80, 192, 5, 102, 102, 153, 27, 0, 0, 0, + 5, 5, 16, 0, 5, 153, 5, 153, 5, 150, 28, 193, 194, 0, 0, 0, + 0, 0, 0, 0, 5, 195, 196, 197, 83, 198, 194, 25, 199, 25, 192, 116, + 5, 5, 194, 200, 5, 32, 201, 16, 5, 153, 202, 203, 5, 5, 204, 0, + 205, 206, 199, 0, 207, 208, 5, 16, 40, 49, 209, 61, 210, 12, 211, 0, + 5, 5, 212, 199, 5, 5, 213, 0, 0, 0, 0, 0, 5, 214, 215, 0, + 5, 103, 216, 0, 5, 217, 0, 0, 66, 163, 218, 0, 0, 0, 0, 0, + 5, 32, 0, 0, 0, 5, 5, 219, 220, 221, 222, 0, 0, 223, 30, 224, + 5, 225, 25, 5, 226, 25, 5, 32, 0, 0, 0, 0, 0, 0, 5, 79, + 227, 228, 79, 148, 171, 229, 0, 0, 230, 231, 232, 233, 234, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 116, 235, 236, 79, 0, 0, 237, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 167, 0, 0, 0, + 5, 5, 5, 140, 5, 5, 5, 5, 5, 5, 61, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 5, 5, 179, + 5, 93, 238, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 74, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 218, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 5, 140, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 32, 103, 25, 5, 103, 25, 156, 5, 93, 61, 239, 93, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 31, 0, 0, 0, 0, + 0, 0, 5, 5, 0, 0, 0, 0, 5, 5, 240, 5, 241, 0, 0, 242, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 243, + 5, 5, 5, 5, 5, 5, 102, 219, 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 245, 246, 202, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 108, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 247, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 249, 5, 250, 251, 252, 5, 253, 254, 255, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 256, 257, 87, 249, 249, 258, 258, 227, 227, 259, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 103, 260, 0, 0, 0, 0, 0, 0, + 261, 262, 5, 156, 135, 0, 0, 0, 5, 263, 264, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 25, 156, 5, 265, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 25, 265, 0, 0, 0, 0, 0, 0, 25, 266, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 267, + 5, 5, 5, 5, 5, 5, 192, 0, 5, 5, 268, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 252, 269, 270, 271, 272, 273, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 162, 162, 107, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 167, 5, 5, 5, 5, 5, 5, + 118, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 274, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 275, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 33, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 93, 0, 0 +}; + +static RE_UINT8 re_posix_alnum_table_3[] = { + 0, 0, 0, 0, 0, 0, 255, 3, 254, 255, 255, 7, 0, 4, 32, 4, + 255, 255, 127, 255, 255, 255, 255, 255, 195, 255, 3, 0, 31, 80, 0, 0, + 32, 0, 0, 0, 248, 255, 223, 188, 64, 215, 255, 255, 251, 255, 255, 255, + 255, 255, 191, 255, 3, 252, 255, 255, 255, 255, 254, 255, 255, 255, 127, 2, + 255, 1, 0, 0, 0, 0, 255, 191, 182, 0, 255, 255, 255, 135, 7, 0, + 0, 0, 255, 7, 255, 255, 255, 254, 0, 192, 255, 255, 255, 255, 239, 31, + 254, 225, 0, 156, 0, 0, 255, 255, 0, 224, 255, 255, 255, 255, 3, 0, + 0, 252, 255, 255, 255, 7, 48, 4, 255, 255, 255, 252, 255, 31, 0, 0, + 255, 255, 255, 1, 255, 7, 255, 255, 255, 126, 128, 0, 255, 3, 240, 255, + 248, 3, 255, 255, 255, 255, 255, 239, 255, 223, 225, 255, 15, 0, 254, 255, + 239, 159, 249, 255, 255, 253, 197, 227, 159, 89, 128, 176, 15, 0, 3, 16, + 238, 135, 249, 255, 255, 253, 109, 195, 135, 25, 2, 94, 0, 0, 63, 0, + 238, 191, 251, 255, 255, 253, 237, 227, 191, 27, 1, 0, 15, 0, 0, 30, + 238, 159, 249, 255, 159, 25, 192, 176, 15, 0, 2, 0, 236, 199, 61, 214, + 24, 199, 255, 195, 199, 29, 129, 0, 255, 223, 253, 255, 255, 253, 255, 227, + 223, 29, 96, 39, 15, 0, 0, 0, 239, 223, 253, 255, 255, 253, 239, 227, + 223, 29, 96, 96, 15, 0, 14, 0, 255, 255, 255, 231, 223, 93, 240, 128, + 15, 0, 0, 252, 238, 255, 127, 252, 255, 255, 251, 47, 127, 128, 95, 255, + 0, 0, 12, 0, 254, 255, 255, 255, 255, 255, 255, 7, 127, 32, 0, 0, + 214, 247, 255, 255, 175, 255, 255, 59, 95, 32, 0, 240, 1, 0, 0, 0, + 255, 254, 255, 255, 255, 31, 254, 255, 15, 255, 255, 254, 255, 255, 255, 31, + 255, 255, 127, 249, 255, 255, 0, 60, 191, 32, 255, 255, 255, 255, 255, 247, + 255, 61, 127, 61, 255, 61, 255, 255, 255, 255, 61, 127, 61, 255, 127, 255, + 255, 255, 61, 255, 255, 255, 0, 0, 255, 255, 63, 63, 255, 159, 255, 255, + 255, 199, 255, 1, 255, 255, 15, 128, 255, 255, 15, 0, 255, 223, 13, 0, + 255, 255, 207, 255, 255, 1, 128, 16, 255, 255, 63, 0, 255, 255, 255, 127, + 255, 15, 255, 1, 255, 63, 31, 0, 255, 15, 255, 255, 255, 3, 0, 0, + 255, 255, 255, 15, 254, 255, 31, 0, 128, 0, 0, 128, 1, 112, 0, 0, + 255, 255, 239, 255, 239, 31, 0, 0, 255, 243, 0, 252, 191, 255, 3, 0, + 255, 255, 127, 0, 0, 224, 0, 252, 255, 255, 255, 63, 0, 222, 111, 4, + 0, 0, 248, 255, 255, 255, 31, 0, 63, 63, 255, 170, 255, 255, 223, 95, + 220, 31, 207, 15, 255, 31, 220, 31, 0, 0, 2, 128, 0, 0, 255, 31, + 132, 252, 47, 62, 80, 189, 255, 243, 224, 67, 0, 0, 0, 0, 192, 255, + 31, 120, 12, 0, 255, 128, 0, 0, 127, 127, 127, 127, 0, 128, 0, 0, + 224, 0, 0, 0, 254, 3, 62, 31, 255, 255, 127, 224, 224, 255, 255, 255, + 255, 127, 0, 0, 255, 31, 255, 255, 0, 12, 0, 0, 255, 127, 240, 143, + 0, 0, 128, 255, 252, 255, 255, 255, 255, 249, 255, 255, 255, 63, 235, 31, + 0, 0, 252, 255, 191, 255, 255, 255, 255, 0, 0, 0, 47, 0, 0, 0, + 0, 0, 252, 232, 255, 255, 7, 0, 255, 255, 247, 255, 255, 255, 0, 124, + 255, 63, 0, 0, 255, 255, 127, 252, 5, 0, 0, 56, 255, 255, 60, 0, + 126, 126, 126, 0, 127, 127, 255, 255, 255, 3, 255, 255, 255, 7, 0, 0, + 15, 0, 255, 255, 127, 248, 255, 255, 255, 63, 255, 255, 255, 255, 255, 3, + 127, 0, 248, 224, 255, 253, 127, 95, 219, 255, 255, 255, 255, 255, 252, 255, + 0, 0, 255, 15, 0, 0, 223, 255, 192, 255, 255, 255, 252, 252, 252, 28, + 255, 239, 255, 255, 127, 255, 255, 183, 255, 63, 255, 63, 255, 255, 1, 0, + 15, 255, 62, 0, 255, 255, 15, 255, 255, 0, 255, 255, 15, 0, 255, 247, + 255, 247, 183, 255, 251, 255, 251, 27, 255, 255, 253, 7, 63, 253, 255, 255, + 255, 255, 191, 145, 255, 255, 55, 0, 255, 255, 255, 192, 111, 240, 239, 254, + 31, 0, 0, 0, 63, 130, 255, 255, 63, 0, 0, 0, 255, 27, 3, 0, + 28, 0, 0, 0, 0, 0, 0, 16, 128, 0, 255, 255, 3, 0, 0, 0, + 0, 0, 62, 0, 4, 0, 255, 255, 240, 0, 255, 255, 255, 255, 71, 0, + 30, 192, 0, 20, 255, 255, 251, 255, 255, 255, 159, 192, 127, 189, 255, 191, + 255, 1, 255, 255, 159, 25, 129, 224, 255, 75, 255, 255, 165, 55, 10, 0, + 187, 7, 0, 128, 179, 0, 0, 0, 255, 255, 63, 127, 0, 0, 0, 63, + 17, 0, 0, 0, 255, 255, 63, 1, 127, 0, 0, 0, 0, 0, 0, 128, + 127, 242, 111, 255, 255, 255, 191, 153, 7, 0, 0, 0, 255, 252, 255, 255, + 26, 0, 0, 0, 255, 255, 231, 127, 255, 255, 255, 32, 255, 253, 255, 255, + 255, 255, 127, 127, 255, 254, 127, 0, 127, 251, 255, 255, 255, 255, 127, 180, + 203, 0, 0, 0, 191, 253, 255, 255, 255, 127, 123, 1, 255, 255, 253, 255, + 255, 255, 255, 199, 0, 0, 1, 0, 126, 0, 0, 0, 248, 255, 255, 224, + 255, 135, 255, 255, 255, 128, 255, 255, 11, 0, 3, 0, 255, 255, 255, 0, + 0, 0, 239, 111, 7, 0, 4, 0, 0, 0, 39, 0, 255, 7, 255, 31, + 255, 1, 255, 67, 255, 255, 223, 255, 255, 255, 255, 223, 100, 222, 255, 235, + 239, 255, 255, 255, 191, 231, 223, 223, 255, 255, 255, 123, 95, 252, 253, 255, + 63, 255, 255, 255, 253, 255, 255, 247, 255, 127, 255, 255, 247, 15, 0, 0, + 224, 7, 0, 0, 127, 255, 255, 249, 219, 7, 255, 255, 255, 31, 128, 63, + 0, 64, 0, 0, 255, 15, 0, 0, 255, 63, 1, 0, 127, 111, 255, 127, + 143, 8, 0, 0, 150, 254, 247, 10, 132, 234, 150, 170, 150, 247, 247, 94, + 255, 251, 255, 15, 238, 251, 255, 15, 3, 0, 255, 255, 1, 0, 255, 255 +}; + +RE_UINT32 re_get_posix_alnum(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_posix_alnum_table_1[field_2]; + v = re_posix_alnum_table_2[(v << 5) | field_1]; + v = re_posix_alnum_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Posix_Digit. */ +RE_UINT32 re_get_posix_digit(RE_UINT32 codepoint) { + if (0x30 <= codepoint && codepoint <= 0x39) + return 1; + + return 0; +} + +/* Posix_Punct. */ +static RE_UINT8 re_posix_punct_table_1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 13, + 13, 13, 13, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 15, 16, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, 13, 27, 13, 28, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 29, 30, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 31, + 13, 13, 13, 32, 33, 34, 35, 13, 36, 37, 38, 39, 40, 41, 42, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13 +}; + +static RE_UINT8 re_posix_punct_table_2[] = { + 0, 1, 2, 3, 0, 4, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 6, 7, 0, 0, 0, 8, 9, 0, 0, 10, + 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 12, 0, 13, 14, 15, 16, + 17, 0, 0, 18, 0, 0, 19, 20, 21, 0, 0, 0, 0, 0, 0, 22, + 0, 23, 14, 0, 24, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 26, + 0, 0, 0, 10, 0, 0, 0, 27, 0, 0, 0, 28, 0, 0, 0, 29, + 0, 0, 0, 30, 31, 0, 0, 0, 0, 0, 32, 33, 0, 0, 0, 34, + 0, 35, 36, 0, 0, 0, 0, 0, 37, 38, 0, 0, 39, 40, 41, 0, + 0, 0, 42, 0, 40, 0, 0, 43, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 45, 0, 0, 0, + 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 47, 48, 0, 0, 49, 0, 50, 0, 0, 0, 0, 51, 0, + 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 0, 0, 0, 40, 54, + 40, 0, 0, 0, 0, 55, 0, 0, 0, 0, 56, 57, 0, 0, 0, 58, + 0, 59, 0, 40, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 62, 63, + 64, 65, 66, 67, 68, 54, 46, 0, 69, 70, 71, 0, 72, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 73, 52, 0, 58, 74, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 74, 75, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 76, 77, 54, 54, 54, + 0, 0, 0, 0, 0, 0, 0, 78, 0, 0, 0, 28, 0, 0, 0, 0, + 54, 79, 80, 0, 81, 54, 54, 82, 54, 54, 54, 54, 54, 54, 74, 64, + 83, 84, 0, 0, 48, 46, 0, 43, 0, 0, 0, 0, 85, 0, 54, 86, + 66, 87, 88, 54, 87, 89, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 64, 54, 90, 40, 0, 0, 0, 0, 0, 0, 0, 0, + 91, 0, 0, 92, 0, 0, 0, 93, 94, 95, 0, 0, 96, 0, 0, 0, + 0, 97, 0, 98, 0, 0, 99, 100, 0, 99, 35, 0, 0, 0, 101, 0, + 0, 0, 58, 102, 0, 0, 40, 27, 0, 0, 43, 103, 0, 0, 0, 104, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 0, 0, 0, 106, 107, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 108, 0, 0, 0, 32, 58, + 45, 64, 109, 110, 0, 0, 0, 0, 1, 2, 2, 111, 0, 0, 0, 112, + 0, 0, 0, 0, 0, 0, 0, 0, 107, 113, 0, 114, 115, 46, 64, 116, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 0, 28, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 117, 0, 0, 0, 0, 35, 35, 0, 0, 0, 0, 0, 0, + 0, 0, 118, 35, 0, 0, 24, 119, 0, 114, 0, 0, 120, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 99, 0, 0, 0, + 0, 0, 0, 0, 0, 122, 0, 0, 0, 0, 123, 0, 124, 0, 0, 0, + 0, 0, 125, 0, 0, 126, 95, 0, 0, 0, 127, 128, 0, 0, 129, 0, + 0, 130, 0, 0, 0, 105, 0, 0, 0, 0, 0, 0, 0, 0, 131, 0, + 0, 0, 132, 0, 0, 0, 133, 0, 0, 0, 0, 0, 0, 0, 134, 0, + 0, 0, 135, 136, 0, 33, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, + 0, 43, 0, 0, 0, 0, 0, 0, 0, 0, 137, 0, 0, 0, 0, 11, + 0, 35, 90, 0, 138, 107, 0, 0, 73, 0, 0, 0, 0, 0, 0, 139, + 0, 0, 140, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 117, 0, 0, 141, 0, 0, 0, 142, 143, + 0, 0, 0, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 99, 0, 0, 0, 146, 0, 113, 147, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, 0, 0, 0, + 0, 0, 0, 0, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, + 0, 0, 0, 0, 149, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 54, 54, 54, 54, 54, 54, 54, 108, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 82, 0, 0, 0, 0, 64, 54, 54, 54, 127, 0, + 54, 54, 54, 54, 54, 54, 54, 74, 54, 150, 54, 151, 152, 153, 54, 52, + 54, 54, 154, 0, 0, 0, 0, 0, 54, 54, 94, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 155, 43, 146, 146, 32, 32, 105, 105, 156, 0, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 0, 148, 0, 157, 158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 159, 0, 0, 0, 121, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, 0, 0, 0, 0, 0, + 54, 160, 54, 54, 82, 161, 162, 74, 163, 108, 42, 42, 87, 21, 0, 164, + 165, 166, 167, 111, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 168, 169, 54, 54, 54, 170, 54, 54, 171, 172, + 160, 54, 173, 54, 65, 174, 95, 0, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 82, 175, 176, 54, 177, 178, 54, 54, 54, 54, 109, 54, 54, 108 +}; + +static RE_UINT8 re_posix_punct_table_3[] = { + 0, 0, 0, 0, 254, 255, 0, 252, 1, 0, 0, 248, 1, 0, 0, 120, + 254, 219, 211, 137, 0, 0, 128, 0, 60, 0, 252, 255, 224, 175, 255, 255, + 0, 0, 32, 64, 176, 0, 0, 0, 0, 0, 64, 0, 4, 0, 0, 0, + 0, 0, 0, 252, 0, 230, 0, 0, 0, 0, 0, 64, 73, 0, 0, 0, + 0, 0, 24, 0, 192, 255, 0, 232, 0, 60, 0, 0, 0, 0, 16, 64, + 0, 2, 0, 96, 255, 63, 0, 0, 0, 0, 192, 195, 0, 0, 255, 127, + 0, 1, 0, 0, 48, 0, 1, 0, 0, 0, 12, 44, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, 248, 7, 0, 0, 128, 128, 16, 0, 0, 0, + 0, 128, 0, 0, 0, 0, 0, 2, 0, 0, 16, 0, 0, 0, 0, 128, + 0, 128, 0, 12, 254, 255, 255, 252, 0, 0, 80, 61, 32, 0, 0, 0, + 0, 0, 0, 192, 191, 223, 255, 7, 0, 252, 0, 0, 0, 0, 0, 8, + 255, 1, 0, 0, 0, 0, 255, 3, 1, 0, 0, 0, 0, 96, 0, 0, + 0, 0, 0, 24, 0, 56, 0, 0, 0, 0, 96, 0, 0, 0, 112, 15, + 255, 7, 0, 0, 49, 0, 0, 0, 255, 255, 255, 255, 127, 63, 0, 0, + 0, 192, 0, 252, 255, 7, 240, 255, 0, 0, 0, 240, 0, 0, 0, 248, + 255, 0, 8, 0, 0, 0, 0, 160, 3, 224, 0, 224, 0, 224, 0, 96, + 0, 0, 255, 255, 255, 0, 255, 255, 255, 255, 255, 127, 0, 0, 0, 124, + 0, 124, 0, 0, 123, 3, 208, 193, 175, 66, 0, 12, 31, 188, 0, 0, + 0, 12, 255, 255, 255, 3, 0, 0, 255, 255, 63, 0, 0, 0, 240, 255, + 255, 255, 207, 255, 255, 255, 191, 255, 224, 7, 0, 222, 255, 127, 255, 255, + 255, 255, 255, 63, 255, 255, 255, 251, 255, 255, 15, 0, 30, 255, 255, 255, + 1, 0, 193, 224, 0, 0, 195, 255, 63, 128, 0, 0, 0, 252, 255, 255, + 255, 0, 1, 0, 255, 255, 1, 0, 127, 0, 0, 0, 0, 224, 0, 0, + 0, 0, 8, 64, 0, 0, 252, 0, 255, 255, 127, 0, 3, 0, 0, 0, + 0, 6, 0, 0, 0, 15, 192, 3, 0, 0, 240, 0, 0, 192, 0, 0, + 0, 0, 0, 23, 254, 63, 0, 192, 0, 0, 128, 3, 0, 12, 0, 0, + 0, 8, 0, 0, 0, 2, 0, 0, 0, 0, 252, 255, 7, 0, 0, 0, + 255, 255, 0, 0, 255, 255, 247, 255, 127, 15, 0, 0, 63, 0, 0, 0, + 127, 127, 0, 48, 0, 0, 128, 255, 0, 0, 0, 254, 255, 115, 255, 31, + 255, 255, 255, 31, 0, 0, 128, 1, 0, 0, 255, 1, 0, 0, 127, 0, + 0, 0, 0, 30, 0, 64, 0, 0, 0, 32, 0, 0, 0, 0, 224, 3, + 192, 3, 0, 0, 128, 63, 0, 0, 0, 0, 0, 216, 15, 0, 0, 0, + 0, 0, 48, 0, 224, 33, 0, 232, 0, 0, 0, 63, 0, 0, 176, 1, + 0, 248, 0, 44, 64, 0, 0, 0, 254, 255, 255, 0, 14, 0, 0, 0, + 255, 31, 0, 0, 112, 0, 0, 0, 0, 0, 0, 220, 2, 0, 0, 0, + 62, 0, 0, 0, 248, 255, 0, 0, 0, 0, 224, 255, 255, 255, 3, 128, + 0, 0, 31, 0, 0, 0, 6, 0, 0, 0, 32, 0, 48, 0, 0, 0, + 0, 0, 128, 7, 0, 0, 0, 144, 127, 254, 255, 255, 31, 28, 0, 0, + 24, 240, 255, 255, 255, 195, 255, 255, 35, 0, 0, 0, 2, 0, 0, 8, + 8, 0, 0, 0, 0, 224, 223, 255, 239, 15, 0, 0, 0, 16, 1, 0, + 255, 15, 255, 255, 255, 127, 254, 255, 254, 255, 254, 255, 0, 224, 255, 255, + 192, 255, 255, 255, 7, 0, 255, 255, 255, 255, 255, 15, 255, 1, 3, 0, + 255, 255, 255, 240, 255, 31, 255, 31, 255, 255, 127, 248, 255, 255, 255, 3, + 255, 15, 1, 0, 255, 0, 255, 3, 255, 63, 255, 15, 255, 63, 255, 31, + 255, 131, 255, 255, 127, 192, 255, 159, 255, 3, 255, 1 +}; + +RE_UINT32 re_get_posix_punct(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_posix_punct_table_1[field_2]; + v = re_posix_punct_table_2[(v << 5) | field_1]; + v = re_posix_punct_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Posix_XDigit. */ +RE_UINT32 re_get_posix_xdigit(RE_UINT32 codepoint) { + if (0x30 <= codepoint && codepoint <= 0x39) + return 1; + if (0x41 <= codepoint && codepoint <= 0x46) + return 1; + if (0x61 <= codepoint && codepoint <= 0x66) + return 1; + + return 0; +} + +/* Prepended_Concatenation_Mark. */ +RE_UINT32 re_get_prepended_concatenation_mark(RE_UINT32 codepoint) { + if (0x0600 <= codepoint && codepoint <= 0x0605) + return 1; + if (codepoint == 0x06DD) + return 1; + if (codepoint == 0x070F) + return 1; + if (0x0890 <= codepoint && codepoint <= 0x0891) + return 1; + if (codepoint == 0x08E2) + return 1; + if (codepoint == 0x0110BD) + return 1; + if (codepoint == 0x0110CD) + return 1; + + return 0; +} + +/* Print. */ +static RE_UINT8 re_print_table_1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 15, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 16, 17, 17, 13, 13, 13, 13, 13, 13, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 17, 30, 13, 31, 13, 13, + 32, 33, 17, 17, 17, 17, 17, 17, 34, 17, 35, 36, 13, 13, 13, 13, + 13, 37, 13, 38, 17, 17, 17, 17, 17, 17, 17, 39, 40, 17, 17, 41, + 17, 17, 17, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 17, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 54, 13, 13, 13, 55, 56, 13, + 13, 13, 13, 57, 13, 13, 13, 13, 13, 13, 58, 59, 17, 17, 60, 17, + 13, 13, 13, 13, 61, 13, 13, 13, 62, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 63, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 64, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 64 +}; + +static RE_UINT16 re_print_table_2[] = { + 0, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 4, 5, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 7, 1, 8, 1, 9, 10, + 1, 1, 1, 1, 1, 1, 1, 1, 11, 1, 12, 1, 1, 13, 1, 14, + 1, 15, 16, 17, 18, 1, 1, 1, 1, 1, 1, 1, 19, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 30, 31, 28, 32, 33, 34, 35, 36, 37, + 38, 39, 40, 41, 38, 42, 43, 44, 38, 1, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 0, 54, 55, 56, 0, 1, 1, 57, 58, 59, 60, 61, 0, + 1, 1, 1, 1, 1, 1, 62, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 63, 1, 64, 65, 66, 1, 67, 1, 14, 68, 69, 1, 1, 70, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 68, 1, 1, 71, 72, 73, 74, 75, 1, 1, 76, 77, + 69, 1, 1, 71, 1, 17, 1, 78, 2, 79, 80, 81, 1, 82, 83, 1, + 84, 1, 2, 85, 77, 86, 87, 0, 1, 1, 88, 1, 1, 1, 1, 89, + 1, 90, 91, 1, 17, 14, 9, 92, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 70, 1, 93, 76, 1, 94, 95, 96, + 1, 97, 1, 98, 99, 1, 100, 101, 1, 1, 1, 1, 82, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 102, 103, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 104, 105, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 106, 1, 62, 1, 107, 73, 108, 108, 1, + 1, 1, 76, 0, 109, 1, 1, 74, 1, 1, 1, 1, 1, 1, 78, 110, + 1, 1, 51, 1, 7, 1, 1, 1, 111, 6, 1, 1, 112, 1, 1, 113, + 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 114, 1, 115, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 116, 1, 1, 1, 1, 1, 117, 1, 1, 1, 1, 1, 1, 118, 119, + 1, 120, 1, 117, 1, 1, 121, 1, 1, 1, 122, 68, 1, 1, 123, 2, + 1, 73, 124, 1, 1, 1, 125, 73, 126, 127, 1, 82, 1, 1, 1, 128, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 129, 130, 53, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 86, 1, 1, 69, 0, 131, 132, 133, 1, 1, 1, 134, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 135, 1, 136, 110, + 69, 1, 137, 138, 1, 1, 1, 85, 51, 1, 1, 1, 1, 2, 139, 140, + 141, 142, 143, 0, 1, 1, 1, 92, 144, 145, 1, 1, 99, 146, 110, 76, + 0, 0, 0, 0, 68, 1, 101, 53, 1, 147, 17, 92, 148, 1, 149, 0, + 1, 1, 1, 1, 76, 150, 151, 53, 1, 9, 1, 152, 153, 154, 1, 74, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 73, 78, 155, 156, 157, 0, 0, + 158, 159, 105, 1, 2, 160, 0, 161, 162, 163, 0, 0, 1, 164, 135, 1, + 165, 166, 167, 1, 1, 0, 1, 168, 1, 169, 170, 171, 172, 173, 0, 0, + 1, 1, 174, 0, 1, 175, 1, 176, 1, 177, 1, 178, 179, 0, 0, 0, + 0, 0, 0, 2, 1, 180, 181, 182, 1, 9, 69, 110, 102, 110, 116, 73, + 1, 1, 183, 72, 1, 1, 184, 185, 1, 94, 9, 73, 1, 1, 1, 186, + 187, 1, 188, 0, 189, 150, 1, 190, 19, 191, 192, 193, 194, 105, 195, 196, + 1, 1, 197, 188, 1, 1, 177, 0, 0, 0, 0, 0, 1, 170, 76, 0, + 1, 1, 198, 199, 1, 69, 150, 200, 14, 82, 201, 0, 0, 0, 0, 0, + 1, 53, 0, 0, 0, 1, 1, 202, 203, 204, 205, 0, 0, 97, 3, 206, + 1, 1, 9, 1, 1, 207, 1, 71, 102, 0, 0, 0, 0, 0, 1, 208, + 209, 210, 211, 114, 135, 212, 0, 0, 213, 214, 177, 215, 216, 102, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 71, 217, 218, 92, 0, 0, 219, 1, 220, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 69, 0, 0, 0, + 1, 1, 1, 221, 1, 1, 1, 1, 1, 1, 200, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 1, 1, 175, + 1, 1, 78, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 92, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 69, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 71, 2, 222, 1, 2, 150, 223, 1, 1, 224, 225, 226, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 69, 0, 0, 0, 0, + 0, 0, 1, 1, 92, 0, 0, 0, 1, 1, 227, 1, 228, 0, 0, 229, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 117, + 1, 1, 1, 1, 1, 1, 78, 230, 174, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 232, 233, 234, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 53, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 235, 236, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 69, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 74, 0, 0, 1, 86, 115, 1, 1, 1, 200, 0, + 1, 1, 1, 1, 1, 1, 1, 78, 1, 237, 1, 1, 1, 1, 1, 103, + 1, 1, 238, 0, 0, 0, 74, 74, 1, 1, 73, 71, 0, 0, 0, 0, + 1, 1, 94, 1, 60, 239, 240, 1, 241, 242, 243, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 244, 1, 1, 1, 1, 1, 1, 1, 1, 245, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 246, 247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2, 248, 0, 0, 0, 0, 0, 0, + 249, 250, 1, 251, 252, 0, 0, 0, 1, 253, 254, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 110, 87, 1, 163, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 110, 69, 0, 0, 0, 0, 0, 0, 110, 52, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, + 1, 1, 1, 1, 1, 1, 256, 0, 1, 1, 257, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 258, 1, 259, 0, 0, 51, 76, 0, 0, 0, 0, 0, 0, + 240, 260, 261, 262, 263, 264, 0, 265, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 82, 1, 1, 74, 266, 267, 78, 1, 1, 1, 1, 1, 251, 0, 268, + 207, 53, 269, 238, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 164, 270, 1, 1, 1, 271, 1, 1, 69, 272, + 82, 1, 177, 1, 9, 273, 188, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 74, 274, 275, 1, 276, 277, 1, 1, 1, 1, 137, 1, 1, 69, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 69, 1, 1, 1, 1, 1, 1, + 76, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 278, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 100, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 226, 0, 0, + 279, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 226, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 76 +}; + +static RE_UINT8 re_print_table_3[] = { + 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 127, 255, 255, 255, 252, + 240, 215, 255, 255, 251, 255, 255, 255, 255, 255, 254, 255, 255, 255, 127, 254, + 255, 231, 254, 255, 255, 0, 255, 255, 255, 135, 31, 0, 255, 191, 255, 255, + 255, 231, 255, 255, 255, 255, 3, 0, 255, 255, 255, 231, 255, 63, 255, 127, + 255, 255, 255, 79, 255, 7, 255, 255, 255, 127, 131, 255, 239, 159, 249, 255, + 255, 253, 197, 243, 159, 121, 128, 176, 207, 255, 255, 127, 238, 135, 249, 255, + 255, 253, 109, 211, 135, 57, 2, 94, 192, 255, 127, 0, 238, 191, 251, 255, + 255, 253, 237, 243, 191, 59, 1, 0, 207, 255, 3, 254, 238, 159, 249, 255, + 159, 57, 224, 176, 207, 255, 255, 0, 236, 199, 61, 214, 24, 199, 255, 195, + 199, 61, 129, 0, 192, 255, 255, 7, 255, 223, 253, 255, 255, 253, 255, 243, + 223, 61, 96, 39, 207, 255, 128, 255, 255, 253, 239, 243, 223, 61, 96, 96, + 207, 255, 14, 0, 223, 253, 240, 255, 207, 255, 255, 255, 238, 255, 127, 252, + 255, 255, 251, 47, 127, 132, 95, 255, 192, 255, 28, 0, 254, 255, 255, 255, + 255, 255, 255, 135, 255, 255, 255, 15, 214, 247, 255, 255, 175, 255, 255, 63, + 95, 127, 255, 243, 255, 254, 255, 255, 255, 31, 254, 255, 255, 255, 255, 254, + 255, 255, 255, 223, 255, 223, 255, 7, 191, 32, 255, 255, 255, 61, 127, 61, + 255, 61, 255, 255, 255, 255, 61, 127, 61, 255, 127, 255, 255, 255, 61, 255, + 255, 255, 255, 31, 255, 255, 255, 3, 255, 255, 63, 63, 255, 255, 255, 1, + 255, 255, 63, 128, 255, 255, 127, 0, 255, 255, 15, 0, 255, 223, 13, 0, + 255, 255, 255, 63, 255, 3, 255, 3, 255, 255, 63, 0, 255, 15, 255, 15, + 241, 255, 255, 255, 255, 63, 31, 0, 255, 15, 255, 255, 255, 3, 255, 199, + 255, 255, 255, 207, 255, 255, 255, 159, 255, 63, 255, 255, 255, 127, 0, 0, + 255, 223, 255, 255, 255, 255, 15, 240, 255, 255, 255, 248, 255, 227, 255, 255, + 255, 255, 255, 7, 63, 63, 255, 170, 255, 255, 223, 255, 223, 255, 207, 239, + 255, 255, 220, 127, 255, 252, 255, 255, 223, 255, 243, 255, 255, 127, 255, 31, + 1, 0, 255, 255, 255, 255, 1, 0, 255, 3, 0, 0, 255, 7, 0, 0, + 255, 255, 207, 255, 255, 255, 191, 255, 255, 255, 15, 254, 255, 128, 1, 128, + 127, 127, 127, 127, 255, 255, 255, 251, 0, 0, 255, 255, 224, 255, 255, 255, + 255, 127, 255, 255, 63, 128, 255, 255, 255, 31, 255, 255, 127, 0, 255, 255, + 255, 15, 0, 0, 255, 255, 255, 0, 255, 63, 235, 31, 0, 0, 252, 255, + 255, 31, 255, 3, 63, 192, 255, 3, 255, 255, 15, 128, 255, 191, 255, 195, + 255, 63, 255, 243, 7, 0, 0, 248, 126, 126, 126, 0, 127, 127, 255, 255, + 255, 63, 255, 3, 15, 0, 255, 255, 127, 248, 255, 255, 127, 0, 248, 224, + 255, 255, 127, 95, 219, 255, 255, 255, 7, 0, 248, 255, 255, 255, 252, 255, + 255, 128, 0, 0, 255, 255, 247, 255, 127, 15, 223, 255, 252, 252, 252, 28, + 127, 127, 0, 62, 255, 239, 255, 255, 127, 255, 255, 183, 255, 63, 255, 63, + 135, 255, 255, 255, 255, 255, 143, 255, 1, 0, 0, 0, 15, 224, 255, 255, + 255, 255, 255, 191, 15, 255, 63, 0, 255, 3, 255, 255, 255, 255, 15, 255, + 15, 128, 255, 247, 255, 247, 183, 255, 251, 255, 251, 27, 255, 0, 0, 0, + 191, 255, 255, 255, 255, 255, 253, 7, 63, 253, 255, 255, 255, 255, 191, 145, + 128, 255, 0, 0, 255, 255, 55, 248, 255, 255, 255, 143, 255, 255, 255, 131, + 255, 255, 255, 240, 111, 240, 239, 254, 255, 255, 63, 135, 255, 1, 255, 1, + 127, 248, 127, 0, 255, 255, 63, 254, 255, 255, 63, 255, 255, 255, 7, 255, + 255, 255, 3, 30, 0, 254, 0, 0, 255, 1, 0, 0, 255, 255, 7, 0, + 255, 255, 7, 252, 255, 0, 255, 3, 63, 254, 255, 255, 63, 192, 0, 0, + 255, 59, 3, 0, 28, 0, 0, 0, 0, 0, 0, 240, 255, 63, 252, 255, + 7, 32, 255, 255, 255, 1, 255, 3, 254, 255, 31, 0, 255, 255, 251, 255, + 3, 0, 0, 0, 127, 189, 255, 191, 255, 7, 255, 3, 255, 253, 237, 251, + 159, 57, 129, 224, 207, 31, 31, 0, 255, 75, 255, 255, 165, 247, 191, 1, + 6, 0, 0, 0, 255, 255, 255, 239, 31, 0, 255, 3, 255, 31, 0, 0, + 15, 0, 0, 0, 127, 0, 0, 0, 255, 255, 7, 128, 127, 242, 111, 255, + 255, 255, 191, 249, 127, 0, 255, 3, 31, 0, 0, 0, 7, 0, 255, 255, + 3, 0, 255, 3, 255, 253, 255, 255, 255, 255, 127, 255, 63, 0, 255, 255, + 255, 254, 127, 0, 127, 251, 255, 255, 255, 255, 127, 180, 191, 253, 255, 255, + 255, 127, 251, 1, 255, 255, 253, 255, 255, 255, 255, 199, 0, 0, 1, 0, + 255, 255, 3, 128, 255, 127, 31, 0, 255, 195, 255, 255, 255, 63, 63, 0, + 63, 0, 255, 251, 251, 255, 255, 224, 255, 255, 0, 0, 255, 135, 255, 255, + 255, 128, 255, 255, 31, 0, 3, 0, 0, 0, 0, 128, 0, 0, 239, 111, + 7, 0, 4, 0, 0, 0, 39, 0, 240, 0, 255, 255, 255, 7, 255, 31, + 255, 1, 255, 243, 127, 254, 255, 255, 63, 0, 0, 0, 100, 222, 255, 235, + 239, 255, 255, 255, 191, 231, 223, 223, 255, 255, 255, 123, 95, 252, 253, 255, + 63, 255, 255, 255, 255, 207, 255, 255, 255, 15, 0, 248, 254, 255, 0, 0, + 224, 7, 0, 0, 127, 255, 255, 249, 219, 7, 255, 255, 255, 63, 0, 0, + 0, 128, 0, 0, 255, 31, 255, 63, 255, 195, 0, 0, 127, 111, 255, 127, + 159, 255, 127, 0, 255, 15, 255, 195, 0, 0, 254, 255, 255, 255, 31, 0, + 150, 254, 247, 10, 132, 234, 150, 170, 150, 247, 247, 94, 255, 251, 255, 15, + 238, 251, 255, 15, 0, 0, 3, 0, 255, 127, 254, 255, 254, 255, 254, 255, + 192, 255, 255, 255, 255, 1, 3, 0, 255, 31, 255, 31, 255, 255, 127, 248, + 255, 15, 1, 0, 255, 63, 255, 15, 255, 63, 255, 31, 255, 131, 255, 255, + 127, 192, 255, 159, 255, 3, 255, 1, 3, 0, 255, 255, 2, 0, 0, 0 +}; + +RE_UINT32 re_get_print(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_print_table_1[field_2]; + v = re_print_table_2[(v << 5) | field_1]; + v = re_print_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Quotation_Mark. */ +static RE_UINT8 re_quotation_mark_table_1[] = { + 0, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 3, 4, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +}; + +static RE_UINT8 re_quotation_mark_table_2[] = { + 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 7, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 0 +}; + +static RE_UINT8 re_quotation_mark_table_3[] = { + 0, 0, 0, 0, 132, 0, 0, 0, 0, 8, 0, 8, 0, 0, 0, 255, + 0, 0, 0, 6, 4, 0, 0, 0, 0, 240, 0, 224, 30, 0, 0, 0, + 12, 0, 0, 0 +}; + +RE_UINT32 re_get_quotation_mark(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_quotation_mark_table_1[field_2]; + v = re_quotation_mark_table_2[(v << 5) | field_1]; + v = re_quotation_mark_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Radical. */ +RE_UINT32 re_get_radical(RE_UINT32 codepoint) { + if (0x2E80 <= codepoint && codepoint <= 0x2E99) + return 1; + if (0x2E9B <= codepoint && codepoint <= 0x2EF3) + return 1; + if (0x2F00 <= codepoint && codepoint <= 0x2FD5) + return 1; + + return 0; +} + +/* Regional_Indicator. */ +RE_UINT32 re_get_regional_indicator(RE_UINT32 codepoint) { + if (0x01F1E6 <= codepoint && codepoint <= 0x01F1FF) + return 1; + + return 0; +} + +/* Script. */ +static RE_UINT8 re_script_table_1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 13, + 13, 13, 13, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 15, 16, 17, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 19, 20, 20, 20, 20, 20, 20, 20, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 20, 33, 34, 35, 34, 34, + 36, 37, 20, 20, 20, 20, 20, 20, 38, 20, 39, 40, 41, 41, 41, 41, + 41, 42, 43, 44, 20, 20, 20, 20, 20, 20, 20, 45, 46, 20, 20, 47, + 20, 20, 20, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 20, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 60, 13, 13, 13, 61, 62, 13, + 13, 13, 13, 63, 13, 13, 13, 13, 13, 13, 64, 65, 20, 20, 66, 20, + 13, 13, 13, 13, 67, 13, 13, 13, 68, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 69, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20 +}; + +static RE_UINT16 re_script_table_2[] = { + 0, 0, 1, 1, 0, 2, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 5, 0, 6, 7, 7, 7, 8, 9, 10, 11, 12, + 13, 13, 13, 13, 14, 13, 13, 13, 13, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 23, 23, 26, 23, 27, 28, 29, 23, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 23, 23, 39, 40, 40, 41, 42, 43, 44, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, + 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, + 79, 80, 81, 82, 83, 84, 85, 82, 86, 86, 87, 88, 89, 90, 91, 82, + 92, 92, 92, 92, 92, 93, 94, 95, 96, 96, 96, 96, 96, 96, 96, 96, + 97, 97, 98, 97, 99, 100, 101, 97, 102, 97, 103, 104, 105, 106, 106, 107, + 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + 108, 108, 108, 108, 109, 110, 110, 111, 112, 113, 114, 115, 116, 116, 117, 118, + 119, 120, 120, 121, 120, 122, 108, 123, 124, 125, 126, 127, 128, 129, 130, 116, + 131, 132, 133, 134, 135, 136, 137, 82, 138, 138, 139, 138, 140, 140, 141, 142, + 143, 144, 145, 146, 147, 148, 149, 150, 4, 151, 152, 153, 4, 154, 7, 7, + 4, 4, 4, 4, 4, 4, 4, 4, 155, 11, 156, 157, 11, 158, 159, 160, + 161, 0, 0, 162, 163, 0, 164, 165, 0, 166, 167, 4, 168, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 169, 170, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 171, 171, 171, 171, 171, 171, 171, 171, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 173, 0, 0, 0, + 174, 174, 174, 4, 175, 175, 175, 176, 93, 177, 178, 179, 180, 181, 181, 13, + 0, 0, 182, 82, 183, 184, 184, 185, 184, 184, 184, 184, 184, 184, 186, 187, + 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 96, 96, 198, 199, 0, 200, + 201, 0, 0, 202, 0, 0, 203, 204, 194, 194, 205, 0, 0, 0, 0, 0, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 0, 0, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, + 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, + 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, + 206, 206, 206, 206, 207, 206, 208, 209, 210, 210, 210, 210, 210, 210, 210, 210, + 210, 211, 13, 13, 13, 212, 212, 213, 0, 214, 4, 4, 215, 4, 216, 217, + 218, 219, 220, 221, 222, 222, 223, 40, 224, 225, 226, 227, 228, 228, 229, 230, + 231, 232, 233, 92, 234, 234, 235, 236, 237, 238, 239, 240, 106, 106, 241, 242, + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 243, 244, 245, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 184, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 184, 246, 184, 184, 247, 82, 248, 249, 250, 23, 23, 23, 251, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 252, 23, 23, 253, 23, 254, 255, + 256, 257, 258, 259, 23, 23, 23, 260, 261, 1, 1, 262, 263, 201, 264, 265, + 266, 267, 268, 82, 269, 269, 269, 270, 271, 272, 11, 11, 273, 274, 187, 275, + 82, 82, 82, 82, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 82, + 287, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, + 302, 302, 302, 302, 302, 302, 302, 302, 302, 303, 304, 305, 306, 307, 82, 82, + 308, 309, 310, 311, 312, 313, 82, 314, 315, 316, 82, 82, 317, 318, 319, 320, + 321, 322, 323, 324, 325, 82, 326, 327, 328, 329, 330, 331, 332, 333, 82, 82, + 334, 334, 335, 82, 336, 337, 336, 338, 339, 340, 341, 342, 343, 82, 82, 82, + 82, 82, 82, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, + 357, 357, 358, 359, 360, 360, 361, 362, 363, 364, 365, 366, 367, 367, 367, 368, + 369, 370, 371, 82, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, + 384, 384, 385, 386, 387, 387, 388, 82, 82, 82, 82, 82, 389, 390, 391, 82, + 392, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 82, 82, 82, 82, 82, + 402, 403, 82, 82, 82, 404, 404, 405, 406, 407, 408, 82, 82, 409, 410, 411, + 412, 412, 413, 414, 414, 415, 416, 417, 418, 82, 82, 82, 82, 82, 419, 420, + 421, 422, 423, 424, 425, 426, 82, 82, 427, 428, 429, 430, 431, 432, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 433, 434, 435, 436, 82, 82, 437, 438, 439, + 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, + 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 441, 82, 82, 82, + 440, 440, 440, 442, 440, 440, 440, 440, 440, 440, 443, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 444, 445, 445, 446, + 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, + 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, + 447, 447, 448, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, + 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, + 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, + 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 449, + 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, + 450, 450, 451, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 452, 453, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, + 212, 454, 455, 456, 457, 458, 459, 460, 461, 461, 462, 463, 464, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 465, 466, 82, 82, 82, 82, + 82, 82, 467, 467, 468, 82, 82, 82, 469, 469, 470, 469, 471, 82, 82, 472, + 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, + 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, + 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, + 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 474, + 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, + 473, 473, 473, 473, 473, 473, 473, 473, 475, 475, 475, 475, 475, 475, 475, 475, + 475, 475, 475, 475, 475, 475, 476, 477, 478, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 479, + 480, 191, 191, 191, 191, 191, 191, 191, 191, 481, 482, 483, 484, 484, 484, 484, + 484, 484, 484, 484, 484, 484, 484, 485, 82, 82, 82, 82, 82, 82, 82, 82, + 486, 486, 486, 487, 488, 489, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 0, 0, 0, 0, 0, 0, 0, 490, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 491, 82, 82, 7, 492, 493, 0, 0, 0, 489, 82, + 0, 0, 0, 0, 0, 0, 0, 494, 0, 495, 0, 496, 497, 498, 0, 170, + 11, 11, 499, 82, 82, 82, 491, 491, 0, 0, 500, 501, 82, 82, 82, 82, + 0, 0, 502, 0, 503, 504, 505, 0, 506, 507, 508, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 509, 0, 0, 0, 0, 0, 0, 0, 0, 510, 0, + 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, + 511, 511, 511, 511, 512, 513, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 514, 515, 82, 82, 82, 82, 82, 82, + 516, 517, 13, 518, 519, 82, 82, 82, 520, 521, 522, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 523, 524, 525, 526, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 527, 528, 82, 82, 82, 82, 82, 82, 529, 530, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 531, + 532, 532, 532, 532, 532, 532, 533, 82, 534, 534, 535, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 536, 0, 537, 82, 82, 261, 182, 82, 82, 82, 82, 82, 82, + 538, 539, 540, 541, 542, 543, 82, 544, 82, 82, 82, 82, 82, 82, 82, 82, + 0, 545, 0, 0, 491, 546, 547, 494, 0, 0, 0, 0, 0, 548, 82, 549, + 550, 551, 552, 553, 82, 82, 82, 82, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 554, 555, 0, 0, 0, 556, 0, 0, 490, 557, + 545, 0, 558, 0, 559, 560, 561, 82, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 491, 562, 563, 0, 564, 565, 0, 0, 0, 0, 258, 0, 0, 490, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 184, 184, 184, 184, 184, 82, 184, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 247, 184, 184, 184, 184, 184, 184, + 566, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 184, 184, 184, 567, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 568, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 566, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, + 566, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 569, 184, 184, 184, 184, 184, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 570, 82, 82, + 571, 0, 0, 0, 82, 82, 82, 82, 7, 7, 7, 7, 7, 7, 7, 572, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82 +}; + +static RE_UINT8 re_script_table_3[] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 1, 5, 5, 5, 0, 0, 5, 5, 5, 5, 1, 5, + 0, 0, 0, 0, 5, 1, 5, 1, 5, 5, 5, 0, 5, 0, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 4, 4, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 0, 0, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 8, 8, 8, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, + 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 1, 10, 10, 10, 10, 10, 10, 1, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 1, 10, 10, 10, 1, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 1, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 4, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 1, 10, 10, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 11, 11, 11, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 13, 13, 13, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 15, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, + 10, 10, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 1, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 4, 4, 4, 4, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 1, 1, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 17, 17, 17, 17, 0, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 17, + 17, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 17, 17, 17, 17, 17, 17, + 17, 0, 17, 0, 0, 0, 17, 17, 17, 17, 0, 0, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 0, 0, 17, 17, 0, 0, 17, 17, 17, 17, 0, + 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 17, 17, 0, 17, + 17, 17, 17, 17, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, + 0, 18, 18, 18, 0, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 18, + 18, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 18, 18, 18, 18, 18, 18, + 18, 0, 18, 18, 0, 18, 18, 0, 18, 18, 0, 0, 18, 0, 18, 18, + 18, 18, 18, 0, 0, 0, 0, 18, 18, 0, 0, 18, 18, 18, 0, 0, + 0, 18, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 0, 18, 0, + 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 19, 19, 19, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 0, 19, + 19, 19, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 0, 19, 19, 19, 19, 19, 19, + 19, 0, 19, 19, 0, 19, 19, 19, 19, 19, 0, 0, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 0, 19, 19, 19, 0, 19, 19, 19, 0, 0, + 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 19, 19, 19, 19, 0, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 0, 0, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 19, 19, + 0, 20, 20, 20, 0, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 20, + 20, 0, 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 20, 20, 20, 20, 20, 20, + 20, 0, 20, 20, 0, 20, 20, 20, 20, 20, 0, 0, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 0, 0, 20, 20, 0, 0, 20, 20, 20, 0, 0, + 0, 0, 0, 0, 0, 20, 20, 20, 0, 0, 0, 0, 20, 20, 0, 20, + 20, 20, 20, 20, 0, 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 21, 21, 0, 21, 21, 21, 21, 21, 21, 0, 0, 0, 21, 21, + 21, 0, 21, 21, 21, 21, 0, 0, 0, 21, 21, 0, 21, 0, 21, 21, + 0, 0, 0, 21, 21, 0, 0, 0, 21, 21, 21, 0, 0, 0, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 0, 0, 0, 0, 21, 21, + 21, 21, 21, 0, 0, 0, 21, 21, 21, 0, 21, 21, 21, 21, 0, 0, + 21, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 0, 0, 0, 0, 0, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 0, 22, 22, + 22, 0, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 0, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 0, 0, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 0, 22, 22, 22, 0, 22, 22, 22, 22, 0, 0, + 0, 0, 0, 0, 0, 22, 22, 0, 22, 22, 22, 0, 0, 22, 0, 0, + 22, 22, 22, 22, 0, 0, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 0, 0, 0, 0, 0, 0, 0, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 0, 23, 23, + 23, 0, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 0, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 0, 23, 23, 23, 23, 23, 0, 0, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 0, 23, 23, 23, 0, 23, 23, 23, 23, 0, 0, + 0, 0, 0, 0, 0, 23, 23, 0, 0, 0, 0, 0, 0, 23, 23, 0, + 23, 23, 23, 23, 0, 0, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 0, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 24, 24, + 24, 0, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 0, 24, 24, 24, 0, 24, 24, 24, 24, 24, 24, + 0, 0, 0, 0, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 0, 0, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 0, 25, 25, 25, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 0, 25, 0, 0, + 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 25, 0, 0, 0, 0, 25, + 25, 25, 25, 25, 25, 0, 25, 0, 25, 25, 25, 25, 25, 25, 25, 25, + 0, 0, 0, 0, 0, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 0, 0, 25, 25, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 0, 0, 0, 0, 1, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 27, 27, 0, 27, 0, 27, 27, 27, 27, 27, 0, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 0, 27, 0, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, + 27, 27, 27, 27, 27, 0, 27, 0, 27, 27, 27, 27, 27, 27, 27, 0, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 27, 27, 27, 27, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 0, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 0, 0, 0, + 0, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 0, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 0, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 0, 28, 28, + 28, 28, 28, 28, 28, 1, 1, 1, 1, 28, 28, 0, 0, 0, 0, 0, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 0, 30, 0, 0, 0, 0, 0, 30, 0, 0, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 1, 30, 30, 30, 30, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, 32, 32, 32, 32, 0, 0, + 32, 32, 32, 32, 32, 32, 32, 0, 32, 0, 32, 32, 32, 32, 0, 0, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, 32, 32, 32, 32, 0, 0, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 0, 32, 32, 32, 32, 0, 0, 32, 32, 32, 32, 32, 32, 32, 0, + 32, 0, 32, 32, 32, 32, 0, 0, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 0, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 0, 32, 32, 32, 32, 0, 0, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, 0, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, 0, 0, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, 0, 0, 0, 0, 0, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 0, 0, 33, 33, 33, 33, 33, 33, 0, 0, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 0, 0, 0, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 1, 1, 1, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 0, 0, 0, 0, 0, 0, 0, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, + 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, + 38, 38, 38, 38, 38, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 0, 40, 40, + 40, 0, 40, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 0, 0, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 0, 0, 0, 0, 0, 0, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 0, 0, 0, 0, 0, 0, + 42, 42, 1, 1, 42, 1, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 0, 0, 0, 0, 0, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 0, 0, 0, 0, 0, 0, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 0, 0, 0, 0, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 0, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 0, 0, 0, 0, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 0, 0, 0, 0, + 43, 0, 0, 0, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 0, 0, + 44, 44, 44, 44, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 0, 0, 0, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 0, 0, 0, 0, 0, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 0, 0, 45, 45, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 0, 0, 46, 46, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 0, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 0, 0, 0, 0, 0, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 0, 0, 0, 0, 0, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, + 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 51, 0, 0, 0, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 0, 0, 0, 51, 51, 51, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 0, 30, 30, 30, + 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 1, 4, 4, 4, 4, 4, 4, 4, 1, 1, 1, 1, 4, 1, 1, + 1, 1, 1, 1, 4, 1, 1, 1, 4, 4, 1, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 5, 5, 5, 5, 5, 7, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 5, 5, + 5, 5, 2, 2, 2, 2, 5, 5, 5, 5, 5, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 7, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 0, 0, 5, 5, 5, 5, 5, 5, 0, 0, + 5, 5, 5, 5, 5, 5, 0, 0, 5, 5, 5, 5, 5, 5, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 0, 5, 0, 5, 0, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 0, 0, 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 0, 0, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 5, 1, 1, 1, 2, 2, 1, 1, 1, 1, + 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, + 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, + 30, 30, 30, 30, 30, 30, 0, 30, 0, 0, 0, 0, 0, 30, 0, 0, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 0, 0, 55, + 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 32, 32, 32, 32, 32, 32, 32, 0, 32, 32, 32, 32, 32, 32, 32, 0, + 32, 32, 32, 32, 32, 32, 32, 0, 32, 32, 32, 32, 32, 32, 32, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 0, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 56, 1, 56, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 56, 56, 56, 56, 56, 56, 56, 56, 56, 4, 4, 4, 4, 31, 31, + 1, 1, 1, 1, 1, 1, 1, 1, 56, 56, 56, 56, 1, 1, 1, 1, + 0, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, + 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, + 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, + 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, + 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, + 57, 57, 57, 57, 57, 57, 57, 0, 0, 4, 4, 1, 1, 57, 57, 57, + 1, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 1, 1, 58, 58, 58, + 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 0, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 0, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 1, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 1, 1, 1, 1, 1, 1, 1, 1, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 0, 0, 0, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, + 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, + 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, + 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, + 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, + 62, 62, 62, 62, 62, 62, 62, 62, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, + 2, 2, 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 0, 0, 0, 0, 0, 0, 0, 0, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 0, 0, 0, 0, 0, 0, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 1, 66, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 0, 0, 0, + 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, + 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, + 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 0, 1, + 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 0, 0, 0, 0, 68, 68, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 0, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 0, 0, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 0, 0, 69, 69, 69, 69, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 70, 70, 70, 70, + 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 32, 32, 32, 32, 32, 32, 0, 0, 32, 32, 32, 32, 32, 32, 0, + 0, 32, 32, 32, 32, 32, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 32, 32, 32, 32, 32, 32, 32, 0, 32, 32, 32, 32, 32, 32, 32, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 5, 2, 2, 2, 2, 1, 1, 0, 0, 0, 0, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, + 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, 0, 0, + 31, 31, 31, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 0, 0, 0, 0, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 0, 0, 0, 0, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 0, 0, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 0, 9, 0, + 9, 9, 0, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 1, 1, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 10, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 7, 7, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 1, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 1, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 1, 1, + 0, 0, 31, 31, 31, 31, 31, 31, 0, 0, 31, 31, 31, 31, 31, 31, + 0, 0, 31, 31, 31, 31, 31, 31, 0, 0, 31, 31, 31, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 0, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 72, 0, 72, 72, 72, 72, 72, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 0, 72, 72, 0, 72, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 0, 0, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 0, 0, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 0, 0, 0, 0, 0, + 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 0, 0, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 0, 0, 0, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 75, 75, + 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 0, 0, 0, 0, 0, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 0, 0, 0, 0, 0, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 0, 78, + 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 0, 0, 0, 0, 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 0, 0, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 0, 0, 0, 0, 0, 0, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 0, 0, 0, 0, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 0, 0, 0, 0, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 0, 0, 0, 0, 0, 0, 0, 0, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 0, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 0, 86, 86, 86, 86, + 86, 86, 86, 0, 86, 86, 0, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 0, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 0, 86, 86, 86, 86, 86, 86, 86, 0, 86, 86, 0, 0, 0, + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 88, 88, 88, 88, 88, 88, 88, 88, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, + 89, 89, 89, 89, 89, 89, 0, 0, 89, 0, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 0, 89, 89, 0, 0, 0, 89, 0, 0, 89, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 0, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 0, + 0, 0, 0, 0, 0, 0, 0, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, + 93, 93, 93, 0, 93, 93, 0, 0, 0, 0, 0, 93, 93, 93, 93, 93, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 0, 0, 0, 94, + 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, + 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 0, 0, 0, 0, 0, 95, + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 0, 0, 0, 0, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 0, 0, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 98, 98, 98, 98, 0, 98, 98, 0, 0, 0, 0, 0, 98, 98, 98, 98, + 98, 98, 98, 98, 0, 98, 98, 98, 0, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 0, 0, 98, 98, 98, 0, 0, 0, 0, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 0, 0, 0, 0, 0, 0, 0, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 0, 0, 0, 0, 0, 0, 0, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, + 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, + 101, 101, 101, 101, 101, 101, 101, 0, 0, 0, 0, 101, 101, 101, 101, 101, + 101, 101, 101, 101, 101, 101, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 0, 0, 0, 102, 102, 102, 102, 102, 102, 102, + 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, + 103, 103, 103, 103, 103, 103, 0, 0, 103, 103, 103, 103, 103, 103, 103, 103, + 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, + 104, 104, 104, 0, 0, 0, 0, 0, 104, 104, 104, 104, 104, 104, 104, 104, + 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, + 105, 105, 0, 0, 0, 0, 0, 0, 0, 105, 105, 105, 105, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 105, 105, 105, 105, 105, 105, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, + 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, + 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, + 107, 107, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, + 107, 107, 107, 0, 0, 0, 0, 0, 0, 0, 107, 107, 107, 107, 107, 107, + 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + 108, 108, 108, 108, 108, 108, 108, 108, 0, 0, 0, 0, 0, 0, 0, 0, + 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 0, 0, 0, 0, 0, 0, + 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, + 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, + 109, 109, 109, 109, 109, 109, 0, 0, 0, 109, 109, 109, 109, 109, 109, 109, + 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, + 109, 109, 109, 109, 109, 109, 0, 0, 0, 0, 0, 0, 0, 0, 109, 109, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, + 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, + 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, + 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 0, 110, 110, 110, 0, 0, + 110, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, + 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, + 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, + 111, 111, 111, 111, 111, 111, 111, 111, 0, 0, 0, 0, 0, 0, 0, 0, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, + 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, + 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, + 115, 115, 115, 115, 115, 115, 115, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, + 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, + 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 0, 0, + 0, 0, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, + 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, + 116, 116, 116, 116, 116, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, + 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, + 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, + 117, 117, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 0, 0, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 0, 0, 0, 0, 0, 0, 0, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 0, 0, 0, 0, 0, 0, + 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, + 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, + 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, + 119, 119, 119, 119, 119, 0, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, + 119, 119, 119, 119, 119, 119, 119, 119, 0, 0, 0, 0, 0, 0, 0, 0, + 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, + 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, + 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 0, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 123, 123, 123, 123, 123, 123, 123, 0, 123, 0, 123, 123, 123, 123, 0, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 0, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 0, 0, 0, 0, 0, 0, + 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, + 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, + 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, + 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 0, 0, 0, 0, 0, + 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 0, 0, 0, 0, 0, 0, + 125, 125, 125, 125, 0, 125, 125, 125, 125, 125, 125, 125, 125, 0, 0, 125, + 125, 0, 0, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 0, 125, 125, 125, 125, 125, 125, + 125, 0, 125, 125, 0, 125, 125, 125, 125, 125, 0, 4, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 0, 0, 125, 125, 0, 0, 125, 125, 125, 0, 0, + 125, 0, 0, 0, 0, 0, 0, 125, 0, 0, 0, 0, 0, 125, 125, 125, + 125, 125, 125, 125, 0, 0, 125, 125, 125, 125, 125, 125, 125, 0, 0, 0, + 125, 125, 125, 125, 125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 0, 126, 0, 0, 126, 0, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 0, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 0, 126, 0, 0, 126, 0, 126, 126, 126, 126, 0, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 0, 126, 126, 0, 0, 0, 0, 0, 0, 0, + 0, 126, 126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 0, 127, 127, 127, + 127, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 0, 0, 0, 0, 0, 0, 0, 0, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 0, 0, 0, 0, 0, 0, + 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, + 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, + 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, + 129, 129, 129, 129, 129, 129, 0, 0, 129, 129, 129, 129, 129, 129, 129, 129, + 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, + 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 0, 0, + 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, + 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, + 130, 130, 130, 130, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 0, 0, 0, 0, 0, 0, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, + 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, + 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, + 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 0, 0, 0, 0, 0, 0, + 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 0, 0, 0, 0, 0, 0, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 0, 0, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 0, 0, 0, 0, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, + 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, + 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, + 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 0, 0, 0, 0, + 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, + 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, + 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, + 134, 134, 134, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, + 135, 135, 135, 135, 135, 135, 135, 0, 0, 135, 0, 0, 135, 135, 135, 135, + 135, 135, 135, 135, 0, 135, 135, 0, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 0, 135, 135, 0, 0, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 0, 0, 0, 0, 0, 0, + 136, 136, 136, 136, 136, 136, 136, 136, 0, 0, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 0, 0, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 136, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 0, 0, 0, 0, 0, 0, 0, 0, + 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, + 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, + 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, + 139, 139, 139, 139, 139, 139, 139, 139, 139, 0, 0, 0, 0, 0, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 0, 0, 0, 0, 0, 0, + 141, 141, 141, 141, 141, 141, 141, 141, 141, 0, 141, 141, 141, 141, 141, 141, + 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, + 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, + 141, 141, 141, 141, 141, 141, 141, 0, 141, 141, 141, 141, 141, 141, 141, 141, + 141, 141, 141, 141, 141, 141, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, + 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 0, 0, 0, + 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, + 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, + 0, 0, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, + 142, 142, 142, 142, 142, 142, 142, 142, 0, 142, 142, 142, 142, 142, 142, 142, + 142, 142, 142, 142, 142, 142, 142, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 143, 143, 143, 143, 143, 143, 143, 0, 143, 143, 0, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 143, 143, 143, 0, 0, 0, 143, 0, 143, 143, 0, 143, + 143, 143, 143, 143, 143, 143, 143, 143, 0, 0, 0, 0, 0, 0, 0, 0, + 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 0, 0, 0, 0, 0, 0, + 144, 144, 144, 144, 144, 144, 0, 144, 144, 0, 144, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 0, + 144, 144, 0, 144, 144, 144, 144, 144, 144, 0, 0, 0, 0, 0, 0, 0, + 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, + 145, 145, 145, 145, 145, 145, 145, 145, 145, 0, 0, 0, 0, 0, 0, 0, + 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, + 146, 0, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, + 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, + 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 0, 0, 0, 146, 146, + 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, + 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, + 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 0, 0, 0, 0, 0, 0, + 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 0, + 147, 147, 147, 147, 147, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 147, 147, 147, 147, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 0, 0, 0, 0, 0, + 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, + 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, + 150, 150, 150, 150, 150, 150, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, + 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, + 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, + 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 0, 0, 0, 0, 0, 0, + 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, + 62, 62, 62, 62, 62, 62, 62, 62, 62, 0, 0, 0, 0, 0, 0, 0, + 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, + 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 0, + 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 0, 0, 0, 0, 152, 152, + 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, + 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, + 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, + 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, + 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 0, + 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 0, 0, 0, 0, 0, 0, + 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, + 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 0, 0, + 154, 154, 154, 154, 154, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, + 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, + 155, 155, 155, 155, 155, 155, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 0, 155, 155, 155, 155, 155, + 155, 155, 0, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, + 155, 155, 155, 155, 155, 155, 155, 155, 0, 0, 0, 0, 0, 155, 155, 155, + 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, + 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, + 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, + 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 0, 0, 0, 0, 0, 0, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 0, 0, 0, 0, 0, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 0, 0, 0, 0, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 0, 0, 0, 0, 0, 0, 0, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 159, 160, 56, 56, 161, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 56, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, + 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, + 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, + 159, 159, 159, 159, 159, 159, 159, 159, 0, 0, 0, 0, 0, 0, 0, 0, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, + 159, 159, 159, 159, 159, 159, 159, 159, 159, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 58, 58, 58, 58, 0, 58, 58, 58, 58, 58, 58, 58, 0, 58, 58, 0, + 58, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, + 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, + 58, 58, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 57, 57, 57, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 58, 58, 58, 58, 0, 0, 0, 0, 0, 0, 0, 0, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 0, 0, 0, 0, + 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, + 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, + 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 0, 0, 0, 0, 0, + 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 0, 0, 0, + 162, 162, 162, 162, 162, 162, 162, 162, 162, 0, 0, 0, 0, 0, 0, 0, + 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 0, 0, 162, 162, 162, 162, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 4, 4, 4, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 4, 4, 4, + 4, 4, 4, 1, 1, 4, 4, 4, 4, 4, 4, 4, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 4, 4, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, + 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, + 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, + 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, + 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 163, 163, 163, 163, + 0, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, + 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 54, 54, 54, 54, 54, 54, 54, 0, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 54, 54, 54, 54, 54, + 54, 54, 0, 54, 54, 0, 54, 54, 54, 54, 54, 0, 0, 0, 0, 0, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, + 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, + 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 0, 0, 0, + 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 0, 0, + 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 0, 0, 0, 0, 164, 164, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, + 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, + 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, + 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, + 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 0, 0, 0, 0, 0, 166, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, + 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, + 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 0, 0, 0, 0, 168, + 32, 32, 32, 32, 32, 32, 32, 0, 32, 32, 32, 32, 0, 32, 32, 0, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, + 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, + 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, + 169, 169, 169, 169, 169, 0, 0, 169, 169, 169, 169, 169, 169, 169, 169, 169, + 169, 169, 169, 169, 169, 169, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, + 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, + 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 0, 0, 0, 0, + 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 0, 0, 0, 0, 170, 170, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 0, 10, 10, 0, 10, 0, 0, 10, 0, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 0, 10, 10, 10, 10, 0, 10, 0, 10, 0, 0, 0, 0, + 0, 0, 10, 0, 0, 0, 0, 10, 0, 10, 0, 10, 0, 10, 10, 10, + 0, 10, 10, 0, 10, 0, 0, 10, 0, 10, 0, 10, 0, 10, 0, 10, + 0, 10, 10, 0, 10, 0, 0, 10, 10, 10, 10, 0, 10, 10, 10, 10, + 10, 10, 10, 0, 10, 10, 10, 10, 0, 10, 10, 10, 10, 0, 10, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, + 0, 10, 10, 10, 0, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 57, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 0, 0, + 56, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 0, 0, 0, 0, 0, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +RE_UINT32 re_get_script(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = codepoint & 0x1F; + + v = re_script_table_1[field_2]; + v = re_script_table_2[(v << 5) | field_1]; + v = re_script_table_3[(v << 5) | field_0]; + + return v; +} + +/* Script_Extensions. */ +static RE_UINT8 script_extensions_table_1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 13, + 13, 13, 13, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 15, 16, 17, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 19, 20, 20, 20, 20, 20, 20, 20, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 20, 33, 34, 35, 34, 34, + 36, 37, 20, 20, 20, 20, 20, 20, 38, 20, 39, 40, 41, 41, 41, 41, + 41, 42, 43, 44, 20, 20, 20, 20, 20, 20, 20, 45, 46, 20, 20, 47, + 20, 20, 20, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 20, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 60, 13, 13, 13, 61, 62, 13, + 13, 13, 13, 63, 13, 13, 13, 13, 13, 13, 64, 65, 20, 20, 66, 20, + 13, 13, 13, 13, 67, 13, 13, 13, 68, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 69, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20 +}; +static RE_UINT16 script_extensions_table_2[] = { + 0, 0, 1, 1, 0, 2, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 16, 16, 16, 17, 16, 16, 16, 16, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 26, 26, 29, 26, 30, 31, 32, 26, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 26, 26, 42, 43, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, + 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, 88, 85, 89, 89, 90, 91, 92, 93, 94, 85, + 95, 95, 96, 95, 95, 97, 98, 99, 100, 100, 100, 100, 100, 100, 100, 100, + 101, 101, 102, 101, 103, 104, 105, 101, 106, 101, 107, 108, 109, 110, 110, 111, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 113, 114, 114, 115, 116, 117, 118, 119, 120, 120, 121, 122, + 123, 124, 124, 125, 124, 126, 112, 127, 128, 129, 130, 131, 132, 133, 134, 120, + 135, 136, 137, 138, 139, 140, 141, 85, 142, 142, 143, 142, 144, 144, 145, 146, + 147, 148, 149, 150, 151, 152, 153, 154, 4, 155, 156, 157, 4, 158, 159, 160, + 4, 4, 4, 4, 4, 4, 4, 4, 161, 14, 162, 163, 14, 164, 165, 166, + 167, 168, 169, 170, 171, 0, 172, 173, 0, 174, 175, 4, 176, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 177, 178, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 179, 179, 179, 179, 179, 179, 179, 179, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 181, 0, 0, 0, + 182, 182, 182, 4, 183, 183, 183, 184, 97, 185, 186, 187, 188, 189, 189, 16, + 190, 191, 192, 85, 193, 194, 194, 195, 194, 194, 194, 194, 194, 194, 196, 197, + 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 100, 100, 208, 209, 210, 211, + 212, 210, 213, 214, 210, 215, 216, 217, 204, 204, 218, 219, 0, 0, 0, 220, + 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, + 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, + 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 0, 0, + 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, + 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, + 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, + 221, 221, 221, 221, 222, 221, 223, 224, 225, 225, 225, 225, 225, 225, 225, 225, + 225, 226, 16, 227, 16, 228, 228, 229, 230, 231, 4, 4, 232, 4, 233, 234, + 235, 236, 237, 238, 239, 239, 240, 241, 242, 243, 244, 245, 246, 246, 247, 248, + 249, 250, 251, 95, 252, 252, 253, 254, 255, 256, 257, 258, 110, 110, 259, 260, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 261, 262, 263, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 194, 194, 194, 194, 194, 194, 194, 194, + 194, 194, 194, 264, 194, 194, 265, 85, 266, 267, 268, 26, 26, 26, 269, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 270, 26, 26, 271, 26, 272, 273, + 274, 275, 276, 277, 26, 26, 26, 278, 279, 1, 1, 280, 281, 212, 282, 283, + 284, 285, 286, 85, 287, 287, 287, 288, 289, 290, 14, 14, 291, 292, 293, 294, + 85, 85, 85, 85, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 85, + 306, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, + 321, 321, 321, 321, 321, 321, 321, 321, 321, 322, 323, 324, 325, 326, 85, 85, + 327, 328, 329, 330, 331, 332, 85, 333, 334, 335, 85, 85, 336, 337, 338, 339, + 340, 341, 342, 343, 344, 85, 345, 346, 347, 348, 349, 350, 351, 352, 85, 85, + 353, 353, 354, 85, 355, 356, 355, 357, 358, 359, 360, 361, 362, 85, 85, 85, + 85, 85, 85, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, + 376, 376, 377, 378, 379, 379, 380, 381, 382, 383, 384, 385, 386, 386, 386, 387, + 388, 389, 390, 85, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, + 403, 403, 404, 405, 406, 406, 407, 85, 85, 85, 85, 85, 408, 409, 410, 85, + 411, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 85, 85, 85, 85, 85, + 421, 422, 85, 85, 85, 423, 423, 424, 425, 426, 427, 85, 85, 428, 429, 430, + 431, 431, 432, 433, 433, 434, 435, 436, 437, 85, 85, 85, 85, 85, 438, 439, + 440, 441, 442, 443, 444, 445, 85, 85, 446, 447, 448, 449, 450, 451, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 452, 453, 454, 455, 85, 85, 456, 457, 458, + 459, 459, 459, 459, 459, 459, 459, 459, 459, 459, 459, 459, 459, 459, 459, 459, + 459, 459, 459, 459, 459, 459, 459, 459, 459, 459, 459, 459, 460, 85, 85, 85, + 459, 459, 459, 461, 459, 459, 459, 459, 459, 459, 462, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 463, 464, 464, 465, + 466, 466, 466, 466, 466, 466, 466, 466, 466, 466, 466, 466, 466, 466, 466, 466, + 466, 466, 466, 466, 466, 466, 466, 466, 466, 466, 466, 466, 466, 466, 466, 466, + 466, 466, 467, 466, 466, 466, 466, 466, 466, 466, 466, 466, 466, 466, 466, 466, + 466, 466, 466, 466, 466, 466, 466, 466, 466, 466, 466, 466, 466, 466, 466, 466, + 466, 466, 466, 466, 466, 466, 466, 466, 466, 466, 466, 466, 466, 466, 466, 466, + 466, 466, 466, 466, 466, 466, 466, 466, 466, 466, 466, 466, 466, 466, 466, 468, + 469, 469, 469, 469, 469, 469, 469, 469, 469, 469, 469, 469, 469, 469, 469, 469, + 469, 469, 470, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 471, 472, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, + 228, 473, 474, 475, 476, 477, 478, 479, 480, 480, 481, 482, 483, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 484, 485, 85, 85, 85, 85, + 85, 85, 486, 486, 487, 85, 85, 85, 488, 488, 489, 488, 490, 85, 85, 491, + 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, + 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, + 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, + 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, 493, + 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, + 492, 492, 492, 492, 492, 492, 492, 492, 494, 494, 494, 494, 494, 494, 494, 494, + 494, 494, 494, 494, 494, 494, 495, 496, 497, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 498, + 499, 201, 201, 201, 201, 201, 201, 201, 201, 500, 501, 502, 503, 503, 503, 503, + 503, 503, 503, 503, 503, 503, 503, 504, 85, 85, 85, 85, 85, 85, 85, 85, + 505, 505, 505, 506, 507, 508, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 0, 0, 0, 0, 0, 0, 0, 509, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 510, 85, 85, 511, 512, 513, 0, 0, 0, 514, 85, + 0, 0, 0, 0, 0, 0, 0, 515, 0, 516, 0, 517, 518, 519, 0, 178, + 14, 14, 520, 85, 85, 85, 510, 510, 0, 0, 521, 522, 85, 85, 85, 85, + 0, 0, 523, 0, 524, 525, 526, 0, 527, 528, 529, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 530, 0, 0, 0, 0, 0, 0, 0, 0, 531, 0, + 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, + 532, 532, 532, 532, 533, 534, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 535, 536, 85, 85, 85, 85, 85, 85, + 537, 538, 16, 539, 540, 85, 85, 85, 541, 542, 543, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 544, 545, 546, 547, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 548, 549, 85, 85, 85, 85, 85, 85, 550, 551, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 552, + 553, 553, 553, 553, 553, 553, 554, 85, 555, 555, 556, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 557, 0, 558, 85, 85, 279, 559, 85, 85, 85, 85, 85, 85, + 560, 561, 562, 563, 564, 565, 85, 566, 85, 85, 85, 85, 85, 85, 85, 85, + 0, 567, 0, 0, 510, 568, 569, 515, 0, 0, 0, 0, 0, 570, 85, 571, + 572, 573, 574, 575, 85, 85, 85, 85, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 576, 577, 0, 0, 0, 578, 0, 0, 509, 579, + 567, 0, 580, 0, 581, 582, 583, 85, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 510, 584, 585, 0, 586, 587, 0, 0, 0, 0, 588, 0, 0, 509, + 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, + 194, 194, 194, 194, 194, 194, 194, 85, 194, 194, 194, 194, 194, 194, 194, 194, + 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, + 194, 194, 194, 194, 194, 194, 194, 194, 194, 265, 194, 194, 194, 194, 194, 194, + 589, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, + 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, + 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, + 194, 194, 194, 194, 194, 590, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, + 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, + 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 591, + 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, + 194, 194, 589, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, + 589, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, + 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 592, 194, 194, 194, 194, 194, + 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, + 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 593, 85, 85, + 594, 0, 0, 0, 85, 85, 85, 85, 511, 511, 511, 511, 511, 511, 511, 595, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85 +}; +static RE_UINT16 script_extensions_table_3[] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 172, 1, 1, 2, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 173, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 174, 1, 174, 174, 174, 1, 175, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 176, 1, 174, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 4, + 190, 192, 4, 193, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 194, 4, 4, 195, 196, 194, 4, 4, 4, 4, 4, 4, 4, 197, 194, 4, + 198, 199, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 200, 4, 4, 200, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 201, 4, 4, 4, 4, 4, 202, 4, + 4, 4, 4, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, + 5, 5, 5, 5, 204, 204, 5, 5, 0, 0, 5, 5, 5, 5, 1, 5, + 0, 0, 0, 0, 5, 1, 5, 1, 5, 5, 5, 0, 5, 0, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 205, 206, 207, 207, 206, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 0, 0, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 208, 8, 0, 0, 8, 8, 8, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, + 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 1, 10, 10, 10, 10, 10, 10, 209, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 209, 210, 10, 10, 211, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 212, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 213, 213, 213, 213, 213, + 213, 213, 213, 213, 213, 213, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 10, 10, 10, 10, 10, 10, + 213, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 215, 10, 10, 10, 10, 10, 10, 10, 10, 1, 10, 10, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 11, 11, 11, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 13, 13, 13, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 15, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, + 10, 10, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 1, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 216, 217, 4, 4, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 218, 219, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 17, 17, 17, 17, 0, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 17, + 17, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 17, 17, 17, 17, 17, 17, + 17, 0, 17, 0, 0, 0, 17, 17, 17, 17, 0, 0, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 0, 0, 17, 17, 0, 0, 17, 17, 17, 17, 0, + 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 17, 17, 0, 17, + 17, 17, 17, 17, 0, 0, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, + 0, 18, 18, 18, 0, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 18, + 18, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 18, 18, 18, 18, 18, 18, + 18, 0, 18, 18, 0, 18, 18, 0, 18, 18, 0, 0, 18, 0, 18, 18, + 18, 18, 18, 0, 0, 0, 0, 18, 18, 0, 0, 18, 18, 18, 0, 0, + 0, 18, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 0, 18, 0, + 0, 0, 0, 0, 0, 0, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, + 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 19, 19, 19, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 0, 19, + 19, 19, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 0, 19, 19, 19, 19, 19, 19, + 19, 0, 19, 19, 0, 19, 19, 19, 19, 19, 0, 0, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 0, 19, 19, 19, 0, 19, 19, 19, 0, 0, + 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 19, 19, 19, 19, 0, 0, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, + 19, 19, 0, 0, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 19, 19, + 0, 20, 20, 20, 0, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 20, + 20, 0, 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 20, 20, 20, 20, 20, 20, + 20, 0, 20, 20, 0, 20, 20, 20, 20, 20, 0, 0, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 0, 0, 20, 20, 0, 0, 20, 20, 20, 0, 0, + 0, 0, 0, 0, 0, 20, 20, 20, 0, 0, 0, 0, 20, 20, 0, 20, + 20, 20, 20, 20, 0, 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 21, 21, 0, 21, 21, 21, 21, 21, 21, 0, 0, 0, 21, 21, + 21, 0, 21, 21, 21, 21, 0, 0, 0, 21, 21, 0, 21, 0, 21, 21, + 0, 0, 0, 21, 21, 0, 0, 0, 21, 21, 21, 0, 0, 0, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 0, 0, 0, 0, 21, 21, + 21, 21, 21, 0, 0, 0, 21, 21, 21, 0, 21, 21, 21, 21, 0, 0, + 21, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 21, 21, 21, 21, 21, 21, 21, 0, 0, 0, 0, 0, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 0, 22, 22, + 22, 0, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 0, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 0, 0, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 0, 22, 22, 22, 0, 22, 22, 22, 22, 0, 0, + 0, 0, 0, 0, 0, 22, 22, 0, 22, 22, 22, 0, 0, 22, 0, 0, + 22, 22, 22, 22, 0, 0, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 0, 0, 0, 0, 0, 0, 0, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 0, 23, 23, + 23, 0, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 0, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 0, 23, 23, 23, 23, 23, 0, 0, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 0, 23, 23, 23, 0, 23, 23, 23, 23, 0, 0, + 0, 0, 0, 0, 0, 23, 23, 0, 0, 0, 0, 0, 0, 23, 23, 0, + 23, 23, 23, 23, 0, 0, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, + 0, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 24, 24, + 24, 0, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 0, 24, 24, 24, 0, 24, 24, 24, 24, 24, 24, + 0, 0, 0, 0, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 0, 0, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 0, 25, 25, 25, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 0, 25, 0, 0, + 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 25, 0, 0, 0, 0, 25, + 25, 25, 25, 25, 25, 0, 25, 0, 25, 25, 25, 25, 25, 25, 25, 25, + 0, 0, 0, 0, 0, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 0, 0, 25, 25, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 0, 0, 0, 0, 1, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 27, 27, 0, 27, 0, 27, 27, 27, 27, 27, 0, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 0, 27, 0, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, + 27, 27, 27, 27, 27, 0, 27, 0, 27, 27, 27, 27, 27, 27, 27, 0, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 27, 27, 27, 27, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 0, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 0, 0, 0, + 0, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 0, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 0, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 0, 28, 28, + 28, 28, 28, 28, 28, 1, 1, 1, 1, 28, 28, 0, 0, 0, 0, 0, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 0, 30, 0, 0, 0, 0, 0, 30, 0, 0, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 227, 30, 30, 30, 30, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, 32, 32, 32, 32, 0, 0, + 32, 32, 32, 32, 32, 32, 32, 0, 32, 0, 32, 32, 32, 32, 0, 0, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, 32, 32, 32, 32, 0, 0, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 0, 32, 32, 32, 32, 0, 0, 32, 32, 32, 32, 32, 32, 32, 0, + 32, 0, 32, 32, 32, 32, 0, 0, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 0, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 0, 32, 32, 32, 32, 0, 0, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, 0, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, 0, 0, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, 0, 0, 0, 0, 0, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 0, 0, 33, 33, 33, 33, 33, 33, 0, 0, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 0, 0, 0, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 228, 228, 228, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 0, 0, 0, 0, 0, 0, 0, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, + 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, + 38, 38, 38, 38, 38, 229, 229, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 0, 40, 40, + 40, 0, 40, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 0, 0, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 0, 0, 0, 0, 0, 0, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 0, 0, 0, 0, 0, 0, + 42, 42, 230, 230, 42, 230, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 0, 0, 0, 0, 0, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 0, 0, 0, 0, 0, 0, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 0, 0, 0, 0, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 0, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 0, 0, 0, 0, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 0, 0, 0, 0, + 43, 0, 0, 0, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 0, 0, + 44, 44, 44, 44, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 0, 0, 0, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 0, 0, 0, 0, 0, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 0, 0, 45, 45, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 0, 0, 46, 46, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 0, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 0, 0, 0, 0, 0, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 0, 0, 0, 0, 0, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, + 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 51, 0, 0, 0, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 0, 0, 0, 51, 51, 51, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 0, 30, 30, 30, + 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, + 231, 232, 231, 233, 232, 234, 234, 235, 234, 235, 236, 232, 235, 235, 232, 232, + 235, 234, 232, 232, 232, 232, 232, 232, 232, 237, 234, 232, 232, 234, 232, 232, + 232, 232, 238, 239, 240, 234, 234, 241, 239, 239, 242, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 5, 5, 5, 5, 5, 7, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 5, 5, + 5, 5, 2, 2, 2, 2, 5, 5, 5, 5, 5, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 7, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, + 200, 200, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 243, 4, 244, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 0, 0, 5, 5, 5, 5, 5, 5, 0, 0, + 5, 5, 5, 5, 5, 5, 0, 0, 5, 5, 5, 5, 5, 5, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 0, 5, 0, 5, 0, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 0, 0, 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 0, 0, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 245, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 246, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 247, 1, 1, 248, 1, 1, + 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 249, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 5, 1, 1, 1, 2, 2, 1, 1, 1, 1, + 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, + 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, + 30, 30, 30, 30, 30, 30, 0, 30, 0, 0, 0, 0, 0, 30, 0, 0, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 0, 0, 55, + 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 32, 32, 32, 32, 32, 32, 32, 0, 32, 32, 32, 32, 32, 32, 32, 0, + 32, 32, 32, 32, 32, 32, 32, 0, 32, 32, 32, 32, 32, 32, 32, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 250, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 251, 252, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 253, 1, 1, 1, + 1, 254, 1, 206, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 0, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 1, 256, 257, 258, 1, 56, 259, 56, 260, 260, 261, 261, 262, 262, 262, 262, + 262, 262, 1, 258, 262, 262, 262, 262, 262, 262, 262, 262, 258, 258, 258, 258, + 1, 56, 56, 56, 56, 56, 56, 56, 56, 56, 263, 263, 263, 263, 31, 31, + 258, 264, 264, 264, 264, 264, 1, 258, 56, 56, 56, 56, 265, 265, 259, 259, + 0, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, + 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, + 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, + 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, + 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, + 57, 57, 57, 57, 57, 57, 57, 0, 0, 264, 264, 264, 264, 57, 57, 57, + 264, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 262, 264, 58, 58, 58, + 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 0, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 0, + 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, + 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, + 259, 259, 259, 259, 259, 259, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 0, + 259, 259, 259, 259, 259, 259, 259, 259, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 1, + 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, + 259, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 1, 1, 1, 1, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 259, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 259, 259, 259, 259, 259, 259, 259, 259, + 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, + 259, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 259, 259, 259, 259, 259, + 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, + 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 1, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 0, 0, 0, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, + 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, + 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 206, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, + 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, + 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, + 62, 62, 62, 62, 62, 62, 62, 62, 0, 0, 0, 0, 0, 0, 0, 0, + 266, 266, 266, 266, 266, 266, 266, 266, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, + 2, 2, 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 0, 0, 0, + 267, 267, 267, 268, 268, 268, 269, 269, 270, 269, 0, 0, 0, 0, 0, 0, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 0, 0, 0, 0, 0, 0, 0, 0, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 0, 0, 0, 0, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 271, 16, 272, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 273, 66, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 0, 0, 0, + 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, + 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, + 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 0, 274, + 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 0, 0, 0, 0, 68, 68, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 0, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 0, 0, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 0, 0, 69, 69, 69, 69, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 70, 70, 70, 70, + 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 32, 32, 32, 32, 32, 32, 0, 0, 32, 32, 32, 32, 32, 32, 0, + 0, 32, 32, 32, 32, 32, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 32, 32, 32, 32, 32, 32, 32, 0, 32, 32, 32, 32, 32, 32, 32, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 5, 2, 2, 2, 2, 1, 1, 0, 0, 0, 0, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, + 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, 0, 0, + 31, 31, 31, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 0, 0, 0, 0, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 0, 0, 0, 0, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 0, 0, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 0, 9, 0, + 9, 9, 0, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 275, 275, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 10, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 276, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 276, 10, 10, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 7, 7, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 258, 258, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 1, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 262, 262, 262, 262, 262, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 264, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 264, 264, + 0, 0, 31, 31, 31, 31, 31, 31, 0, 0, 31, 31, 31, 31, 31, 31, + 0, 0, 31, 31, 31, 31, 31, 31, 0, 0, 31, 31, 31, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 0, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 72, 0, 72, 72, 72, 72, 72, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 0, 72, 72, 0, 72, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 0, 0, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 0, 0, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 0, 0, 0, 0, 0, + 277, 277, 278, 0, 0, 0, 0, 279, 279, 279, 279, 279, 279, 279, 279, 279, + 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, + 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, + 279, 279, 279, 279, 0, 0, 0, 278, 278, 278, 278, 278, 278, 278, 278, 278, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 0, 0, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 0, 0, 0, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, + 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 0, 0, 0, 0, + 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 75, 75, + 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 0, 0, 0, 0, 0, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 0, 0, 0, 0, 0, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 0, 78, + 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 0, 0, 0, 0, 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 0, 0, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 0, 0, 0, 0, 0, 0, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 0, 0, 0, 0, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 0, 0, 0, 0, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 0, 0, 0, 0, 0, 0, 0, 0, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 0, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 0, 86, 86, 86, 86, + 86, 86, 86, 0, 86, 86, 0, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 0, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 0, 86, 86, 86, 86, 86, 86, 86, 0, 86, 86, 0, 0, 0, + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 88, 88, 88, 88, 88, 88, 88, 88, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, + 89, 89, 89, 89, 89, 89, 0, 0, 89, 0, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 0, 89, 89, 0, 0, 0, 89, 0, 0, 89, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 0, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 0, + 0, 0, 0, 0, 0, 0, 0, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, + 93, 93, 93, 0, 93, 93, 0, 0, 0, 0, 0, 93, 93, 93, 93, 93, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 0, 0, 0, 94, + 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, + 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 0, 0, 0, 0, 0, 95, + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 0, 0, 0, 0, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 0, 0, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 98, 98, 98, 98, 0, 98, 98, 0, 0, 0, 0, 0, 98, 98, 98, 98, + 98, 98, 98, 98, 0, 98, 98, 98, 0, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 0, 0, 98, 98, 98, 0, 0, 0, 0, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 0, 0, 0, 0, 0, 0, 0, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 0, 0, 0, 0, 0, 0, 0, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, + 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, + 101, 101, 101, 101, 101, 101, 101, 0, 0, 0, 0, 101, 101, 101, 101, 101, + 101, 101, 281, 101, 101, 101, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 0, 0, 0, 102, 102, 102, 102, 102, 102, 102, + 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, + 103, 103, 103, 103, 103, 103, 0, 0, 103, 103, 103, 103, 103, 103, 103, 103, + 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, + 104, 104, 104, 0, 0, 0, 0, 0, 104, 104, 104, 104, 104, 104, 104, 104, + 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, + 105, 105, 0, 0, 0, 0, 0, 0, 0, 105, 105, 105, 105, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 105, 105, 105, 105, 105, 105, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, + 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, + 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, + 107, 107, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, + 107, 107, 107, 0, 0, 0, 0, 0, 0, 0, 107, 107, 107, 107, 107, 107, + 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + 108, 108, 108, 108, 108, 108, 108, 108, 0, 0, 0, 0, 0, 0, 0, 0, + 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 0, 0, 0, 0, 0, 0, + 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, + 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, + 109, 109, 109, 109, 109, 109, 0, 0, 0, 109, 109, 109, 109, 109, 109, 109, + 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, + 109, 109, 109, 109, 109, 109, 0, 0, 0, 0, 0, 0, 0, 0, 109, 109, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, + 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, + 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, + 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 0, 110, 110, 110, 0, 0, + 110, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, + 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, + 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, + 111, 111, 111, 111, 111, 111, 111, 111, 0, 0, 0, 0, 0, 0, 0, 0, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, + 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, + 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, + 115, 115, 115, 115, 115, 115, 115, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, + 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, + 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 0, 0, + 0, 0, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, + 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, + 116, 116, 116, 116, 116, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, + 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, + 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, + 117, 117, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 0, 0, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 0, 0, 0, 0, 0, 0, 0, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 0, 0, 0, 0, 0, 0, + 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, + 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, + 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, + 119, 119, 119, 119, 119, 0, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, + 119, 119, 119, 119, 119, 119, 119, 119, 0, 0, 0, 0, 0, 0, 0, 0, + 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, + 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, + 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 0, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 123, 123, 123, 123, 123, 123, 123, 0, 123, 0, 123, 123, 123, 123, 0, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 0, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 0, 0, 0, 0, 0, 0, + 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, + 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, + 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, + 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 0, 0, 0, 0, 0, + 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 0, 0, 0, 0, 0, 0, + 125, 224, 125, 224, 0, 125, 125, 125, 125, 125, 125, 125, 125, 0, 0, 125, + 125, 0, 0, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 0, 125, 125, 125, 125, 125, 125, + 125, 0, 125, 125, 0, 125, 125, 125, 125, 125, 0, 224, 224, 125, 125, 125, + 125, 125, 125, 125, 125, 0, 0, 125, 125, 0, 0, 125, 125, 125, 0, 0, + 125, 0, 0, 0, 0, 0, 0, 125, 0, 0, 0, 0, 0, 125, 125, 125, + 125, 125, 125, 125, 0, 0, 125, 125, 125, 125, 125, 125, 125, 0, 0, 0, + 125, 125, 125, 125, 125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 0, 126, 0, 0, 126, 0, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 0, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 0, 126, 0, 0, 126, 0, 126, 126, 126, 126, 0, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 0, 126, 126, 0, 0, 0, 0, 0, 0, 0, + 0, 126, 126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 0, 127, 127, 127, + 127, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 0, 0, 0, 0, 0, 0, 0, 0, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 0, 0, 0, 0, 0, 0, + 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, + 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, + 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, + 129, 129, 129, 129, 129, 129, 0, 0, 129, 129, 129, 129, 129, 129, 129, 129, + 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, + 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 0, 0, + 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, + 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, + 130, 130, 130, 130, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 0, 0, 0, 0, 0, 0, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, + 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, + 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, + 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 0, 0, 0, 0, 0, 0, + 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 0, 0, 0, 0, 0, 0, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 0, 0, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 0, 0, 0, 0, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, + 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, + 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, + 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 0, 0, 0, 0, + 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, + 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, + 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, + 134, 134, 134, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, + 135, 135, 135, 135, 135, 135, 135, 0, 0, 135, 0, 0, 135, 135, 135, 135, + 135, 135, 135, 135, 0, 135, 135, 0, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 0, 135, 135, 0, 0, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 0, 0, 0, 0, 0, 0, + 136, 136, 136, 136, 136, 136, 136, 136, 0, 0, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 0, 0, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 136, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 0, 0, 0, 0, 0, 0, 0, 0, + 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, + 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, + 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, + 139, 139, 139, 139, 139, 139, 139, 139, 139, 0, 0, 0, 0, 0, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 0, 0, 0, 0, 0, 0, + 141, 141, 141, 141, 141, 141, 141, 141, 141, 0, 141, 141, 141, 141, 141, 141, + 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, + 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, + 141, 141, 141, 141, 141, 141, 141, 0, 141, 141, 141, 141, 141, 141, 141, 141, + 141, 141, 141, 141, 141, 141, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, + 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 0, 0, 0, + 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, + 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, + 0, 0, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, + 142, 142, 142, 142, 142, 142, 142, 142, 0, 142, 142, 142, 142, 142, 142, 142, + 142, 142, 142, 142, 142, 142, 142, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 143, 143, 143, 143, 143, 143, 143, 0, 143, 143, 0, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 143, 143, 143, 0, 0, 0, 143, 0, 143, 143, 0, 143, + 143, 143, 143, 143, 143, 143, 143, 143, 0, 0, 0, 0, 0, 0, 0, 0, + 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 0, 0, 0, 0, 0, 0, + 144, 144, 144, 144, 144, 144, 0, 144, 144, 0, 144, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 0, + 144, 144, 0, 144, 144, 144, 144, 144, 144, 0, 0, 0, 0, 0, 0, 0, + 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, + 145, 145, 145, 145, 145, 145, 145, 145, 145, 0, 0, 0, 0, 0, 0, 0, + 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, + 146, 0, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, + 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, + 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 0, 0, 0, 146, 146, + 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, + 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 224, 224, 21, 224, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, + 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 0, 0, 0, 0, 0, 0, + 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 0, + 147, 147, 147, 147, 147, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 147, 147, 147, 147, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 0, 0, 0, 0, 0, + 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, + 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, + 150, 150, 150, 150, 150, 150, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, + 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, + 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, + 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 0, 0, 0, 0, 0, 0, + 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, + 62, 62, 62, 62, 62, 62, 62, 62, 62, 0, 0, 0, 0, 0, 0, 0, + 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, + 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 0, + 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 0, 0, 0, 0, 152, 152, + 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, + 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, + 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, + 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, + 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 0, + 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 0, 0, 0, 0, 0, 0, + 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, + 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 0, 0, + 154, 154, 154, 154, 154, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, + 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, + 155, 155, 155, 155, 155, 155, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 0, 155, 155, 155, 155, 155, + 155, 155, 0, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, + 155, 155, 155, 155, 155, 155, 155, 155, 0, 0, 0, 0, 0, 155, 155, 155, + 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, + 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, + 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, + 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 0, 0, 0, 0, 0, 0, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 0, 0, 0, 0, 0, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 0, 0, 0, 0, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 0, 0, 0, 0, 0, 0, 0, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 159, 160, 56, 56, 161, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 56, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, + 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, + 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, + 159, 159, 159, 159, 159, 159, 159, 159, 0, 0, 0, 0, 0, 0, 0, 0, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, + 159, 159, 159, 159, 159, 159, 159, 159, 159, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 58, 58, 58, 58, 0, 58, 58, 58, 58, 58, 58, 58, 0, 58, 58, 0, + 58, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, + 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, + 58, 58, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 57, 57, 57, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 58, 58, 58, 58, 0, 0, 0, 0, 0, 0, 0, 0, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 0, 0, 0, 0, + 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, + 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, + 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 0, 0, 0, 0, 0, + 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 0, 0, 0, + 162, 162, 162, 162, 162, 162, 162, 162, 162, 0, 0, 0, 0, 0, 0, 0, + 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 0, 0, 162, 162, 162, 162, + 253, 253, 253, 253, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 4, 4, 4, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 4, 4, 4, + 4, 4, 4, 1, 1, 4, 4, 4, 4, 4, 4, 4, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 4, 4, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, + 259, 259, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, + 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, + 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, + 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, + 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 163, 163, 163, 163, + 0, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, + 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 54, 54, 54, 54, 54, 54, 54, 0, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 54, 54, 54, 54, 54, + 54, 54, 0, 54, 54, 0, 54, 54, 54, 54, 54, 0, 0, 0, 0, 0, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, + 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, + 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 0, 0, 0, + 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 0, 0, + 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 0, 0, 0, 0, 164, 164, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, + 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, + 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, + 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, + 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 0, 0, 0, 0, 0, 166, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, + 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, + 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 0, 0, 0, 0, 168, + 32, 32, 32, 32, 32, 32, 32, 0, 32, 32, 32, 32, 0, 32, 32, 0, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, + 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, + 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, + 169, 169, 169, 169, 169, 0, 0, 169, 169, 169, 169, 169, 169, 169, 169, 169, + 169, 169, 169, 169, 169, 169, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, + 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, + 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 0, 0, 0, 0, + 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 0, 0, 0, 0, 170, 170, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 0, 10, 10, 0, 10, 0, 0, 10, 0, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 0, 10, 10, 10, 10, 0, 10, 0, 10, 0, 0, 0, 0, + 0, 0, 10, 0, 0, 0, 0, 10, 0, 10, 0, 10, 0, 10, 10, 10, + 0, 10, 10, 0, 10, 0, 0, 10, 0, 10, 0, 10, 0, 10, 0, 10, + 0, 10, 10, 0, 10, 0, 0, 10, 10, 10, 10, 0, 10, 10, 10, 10, + 10, 10, 10, 0, 10, 10, 10, 10, 0, 10, 10, 10, 10, 0, 10, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, + 0, 10, 10, 10, 0, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 57, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, + 259, 259, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 0, 0, + 56, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 0, 0, 0, 0, 0, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; +static RE_UINT16 script_extensions_table_4[] = { + 0, 17, 25, 28, 31, 34, 43, 52, 57, 63, 75, 82, 87, 97, 108, 111, + 115, 120, 124, 127, 130, 134, 139, 142, 148, 153, 157, 161, 168, 170, 173, 177, + 179, 182, 185, 188, 191, 195, 203, 207, 216, 226, 229, 233, 236, 250, 263, 285, + 309, 314, 318, 321, 324, 327, 331, 335, 339, 341, 346, 349, 354, 356, 360, 363, + 366, 373, 376, 388, 391, 396, 398, 400, 404, 406, 410, 413, 420, 425, 429, 432, + 435, 443, 445, 449, 452, 460, 469, 475, 477, 486, 496, 503, 506, 509, 513, 516, + 533, 549, 561, 574, 578, 581, 585, 588, 591, 594, 598, 601, 605, 608 +}; +static RE_UINT8 script_extensions_table_5[] = { + 102, 74, 6, 162, 84, 30, 54, 144, 76, 5, 56, 2, 95, 120, 77, 81, + 0, 17, 7, 16, 2, 60, 26, 165, 0, 3, 2, 0, 2, 60, 0, 2, + 26, 0, 33, 6, 7, 5, 2, 77, 140, 44, 0, 33, 7, 5, 2, 83, + 140, 44, 87, 0, 33, 7, 2, 55, 0, 54, 2, 140, 11, 26, 0, 85, + 33, 6, 7, 76, 5, 2, 83, 11, 55, 87, 0, 6, 84, 54, 76, 58, + 2, 0, 7, 5, 2, 77, 0, 6, 162, 9, 2, 77, 11, 44, 55, 87, + 0, 8, 7, 162, 76, 5, 9, 2, 77, 11, 44, 0, 2, 55, 0, 162, + 2, 11, 0, 33, 7, 2, 83, 0, 33, 2, 44, 0, 2, 140, 0, 32, + 2, 0, 7, 2, 87, 0, 5, 2, 77, 87, 0, 2, 11, 0, 33, 162, + 58, 2, 11, 0, 33, 162, 2, 11, 0, 2, 140, 11, 0, 33, 2, 11, + 0, 85, 33, 76, 2, 140, 26, 0, 5, 0, 2, 83, 0, 85, 2, 87, + 0, 2, 0, 6, 5, 0, 7, 77, 0, 7, 54, 0, 7, 2, 0, 8, + 30, 54, 0, 10, 109, 13, 108, 11, 12, 110, 0, 10, 11, 12, 0, 170, + 10, 109, 13, 108, 11, 12, 110, 0, 170, 10, 15, 101, 113, 105, 108, 112, + 11, 0, 10, 11, 0, 10, 12, 110, 0, 10, 108, 0, 17, 16, 125, 19, + 18, 23, 2, 24, 20, 121, 21, 22, 128, 0, 17, 16, 125, 19, 18, 23, + 2, 24, 20, 21, 22, 128, 0, 17, 16, 133, 144, 143, 125, 19, 18, 23, + 120, 24, 136, 168, 20, 124, 25, 63, 131, 21, 22, 128, 0, 17, 16, 133, + 144, 143, 125, 19, 151, 18, 23, 43, 120, 24, 136, 168, 20, 124, 25, 63, + 131, 21, 22, 128, 0, 16, 133, 117, 120, 0, 17, 119, 63, 0, 18, 123, + 0, 19, 122, 0, 125, 21, 0, 23, 136, 126, 0, 119, 29, 44, 0, 30, + 54, 2, 0, 36, 0, 39, 38, 40, 37, 0, 42, 64, 0, 17, 16, 125, + 23, 0, 16, 0, 16, 125, 23, 0, 17, 16, 0, 16, 121, 0, 16, 23, + 24, 20, 21, 22, 0, 16, 136, 0, 17, 16, 125, 23, 24, 136, 20, 25, + 22, 128, 126, 0, 16, 125, 0, 16, 125, 23, 126, 0, 17, 0, 136, 0, + 7, 2, 11, 0, 11, 0, 2, 42, 64, 0, 170, 10, 0, 74, 30, 54, + 107, 73, 106, 0, 74, 5, 107, 96, 0, 16, 125, 2, 0, 6, 2, 0, + 102, 106, 0, 102, 74, 30, 107, 117, 95, 14, 0, 162, 0, 170, 10, 107, + 0, 56, 159, 0, 3, 31, 56, 57, 58, 42, 59, 0, 3, 31, 56, 57, + 58, 42, 64, 59, 0, 3, 31, 56, 57, 58, 0, 56, 0, 3, 31, 56, + 57, 58, 42, 28, 59, 0, 3, 31, 56, 57, 58, 60, 42, 28, 59, 0, + 3, 31, 56, 57, 58, 59, 0, 3, 56, 0, 57, 58, 0, 56, 57, 58, + 0, 56, 2, 0, 16, 133, 19, 18, 122, 23, 117, 120, 24, 130, 136, 121, + 124, 131, 128, 126, 0, 16, 133, 19, 18, 122, 23, 117, 120, 130, 136, 121, + 124, 131, 128, 126, 0, 16, 133, 19, 18, 122, 117, 120, 130, 124, 131, 128, + 0, 16, 133, 19, 18, 122, 117, 120, 130, 121, 124, 131, 128, 0, 17, 16, + 126, 0, 16, 21, 0, 66, 2, 29, 0, 46, 68, 0, 10, 13, 0, 10, + 12, 0, 148, 89, 72, 0, 89, 72, 0, 89, 88, 72, 0, 10, 6, 0, + 101, 113, 0 +}; + +int re_get_script_extensions(RE_UINT32 codepoint, RE_UINT8* scripts) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 v; + int offset; + int count; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = codepoint & 0x1F; + + v = script_extensions_table_1[field_2]; + v = script_extensions_table_2[(v << 5) | field_1]; + v = script_extensions_table_3[(v << 5) | field_0]; + + if (v < 172) { + scripts[0] = v; + + return 1; + } + + offset = script_extensions_table_4[v - 172]; + count = 0; + + do { + scripts[count] = script_extensions_table_5[offset + count]; + ++count; + } while (script_extensions_table_5[offset + count] != 0); + + return count; +} + +/* Sentence_Break. */ +static RE_UINT8 re_sentence_break_table_1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 13, + 13, 13, 13, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 15, 16, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 18, 31, 13, 32, 13, 13, + 33, 34, 18, 18, 18, 18, 18, 18, 35, 18, 36, 37, 13, 13, 13, 13, + 13, 38, 13, 39, 18, 18, 18, 18, 18, 18, 18, 40, 41, 18, 18, 42, + 18, 18, 18, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 18, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 55, 13, 13, 13, 56, 57, 13, + 13, 13, 13, 58, 13, 13, 13, 13, 13, 13, 59, 60, 18, 18, 61, 18, + 13, 13, 13, 13, 62, 13, 13, 13, 63, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 64, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18 +}; + +static RE_UINT16 re_sentence_break_table_2[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 8, 16, 17, 18, 19, 20, 21, 22, 23, 23, 23, 24, 25, 26, 27, 28, + 29, 30, 18, 8, 31, 8, 32, 8, 8, 33, 34, 18, 35, 36, 37, 38, + 39, 40, 41, 42, 40, 40, 43, 44, 45, 46, 47, 40, 40, 48, 49, 50, + 51, 52, 53, 54, 55, 40, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, + 66, 67, 68, 69, 70, 71, 72, 73, 74, 71, 75, 76, 77, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, + 97, 98, 99, 100, 101, 102, 103, 100, 104, 105, 106, 107, 108, 109, 110, 100, + 40, 111, 112, 113, 114, 29, 115, 116, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 117, 40, 118, 119, 120, 40, 121, 40, 122, 123, 124, 29, 29, 125, + 97, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 126, 127, 40, 40, 128, 129, 130, 131, 132, 40, 133, 134, 135, + 136, 40, 40, 137, 138, 139, 40, 140, 141, 142, 143, 144, 40, 145, 146, 100, + 147, 40, 148, 149, 150, 151, 152, 100, 153, 133, 154, 155, 156, 157, 40, 158, + 40, 159, 160, 161, 162, 163, 164, 165, 18, 18, 18, 18, 18, 18, 23, 23, + 8, 8, 8, 8, 166, 8, 8, 8, 167, 168, 169, 170, 168, 171, 172, 173, + 174, 175, 176, 177, 178, 100, 179, 180, 181, 182, 183, 30, 184, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 185, 186, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 187, 30, 188, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 189, 190, 100, 100, 191, 192, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 193, 100, 194, 195, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 29, 30, 18, 196, 8, 8, 8, 197, 18, 198, 40, 199, 200, 201, 201, 23, + 202, 203, 204, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 205, 206, 97, 40, 207, 97, 40, 208, 209, 210, 40, 40, 211, 40, 100, 212, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 100, 100, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 213, 100, 212, 214, 40, 40, 40, 40, 40, 40, 40, 40, + 215, 216, 8, 217, 218, 40, 40, 219, 220, 221, 8, 222, 223, 224, 225, 226, + 227, 228, 40, 229, 230, 133, 231, 232, 49, 233, 234, 235, 58, 236, 237, 238, + 40, 239, 240, 241, 40, 242, 243, 244, 245, 246, 247, 248, 18, 18, 40, 249, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 250, 251, 252, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 253, 40, 40, 254, 100, 255, 256, 257, 40, 40, 258, 259, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 260, 212, 40, 261, 40, 262, 263, + 264, 265, 266, 267, 40, 40, 40, 268, 269, 2, 270, 271, 272, 141, 273, 274, + 275, 276, 277, 100, 40, 40, 40, 278, 100, 100, 40, 279, 100, 100, 100, 280, + 100, 100, 100, 100, 235, 40, 281, 282, 40, 283, 54, 284, 285, 40, 286, 100, + 29, 287, 288, 40, 285, 289, 290, 291, 40, 292, 40, 293, 294, 295, 40, 296, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 200, 140, 262, 297, 298, 100, 100, + 299, 300, 140, 200, 141, 100, 100, 301, 140, 254, 100, 100, 40, 302, 100, 100, + 303, 304, 305, 235, 235, 100, 106, 306, 40, 140, 140, 307, 258, 100, 100, 100, + 40, 40, 308, 100, 29, 309, 18, 310, 40, 311, 312, 313, 314, 100, 100, 100, + 100, 100, 100, 100, 40, 315, 316, 317, 235, 318, 319, 212, 320, 212, 321, 200, + 156, 322, 323, 324, 156, 325, 326, 327, 156, 328, 329, 330, 156, 236, 331, 100, + 332, 333, 334, 100, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, + 40, 347, 348, 349, 40, 46, 350, 100, 100, 100, 100, 100, 40, 351, 352, 100, + 40, 46, 353, 100, 40, 354, 355, 356, 122, 357, 358, 100, 100, 100, 100, 100, + 40, 359, 100, 100, 100, 29, 18, 360, 361, 362, 363, 100, 100, 364, 365, 366, + 367, 368, 369, 40, 370, 212, 40, 137, 100, 100, 100, 100, 100, 100, 40, 371, + 372, 373, 374, 375, 376, 377, 100, 100, 378, 379, 380, 381, 382, 135, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 383, 384, 385, 386, 100, 100, 387, 100, 100, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 254, 100, 100, 100, + 40, 40, 40, 211, 40, 40, 40, 40, 40, 40, 388, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 212, 40, 40, 281, + 40, 389, 390, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 278, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 358, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 272, 391, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 137, 141, 392, 40, 141, 393, 394, 40, 395, 396, 397, 124, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 40, 398, 100, 100, 100, 100, + 100, 100, 29, 18, 399, 100, 100, 100, 40, 40, 400, 23, 401, 100, 100, 402, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 403, + 40, 40, 40, 40, 40, 40, 140, 404, 308, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 405, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 406, 407, 408, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 252, 100, 100, 100, 100, 100, 100, 100, 100, + 40, 40, 40, 409, 410, 411, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 412, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 23, 413, 414, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 415, 416, 417, 100, 100, + 100, 100, 418, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 419, 420, 432, + 422, 433, 434, 435, 426, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 23, 447, 23, 448, 449, 450, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 451, 452, 100, 100, 100, 100, 100, 100, + 453, 454, 18, 455, 456, 100, 100, 100, 40, 457, 458, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 212, 459, 40, 460, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 212, 460, 100, 100, 100, 100, 100, 100, 212, 461, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 462, + 40, 40, 40, 40, 40, 40, 463, 100, 29, 464, 465, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 466, 467, 468, 469, 470, 471, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 472, 473, 473, 474, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 475, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 412, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 100, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 254, 40, 40, 40, 40, 40, 40, + 285, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 476, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 477, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 285, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 285, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 54, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 124, 100, 100, + 478, 23, 23, 23, 100, 100, 100, 100, 23, 23, 23, 23, 23, 23, 23, 479, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 +}; + +static RE_UINT8 re_sentence_break_table_3[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 1, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 4, 5, 0, 0, 0, 0, 5, 5, 5, 0, 0, 6, 6, 7, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 6, 6, 0, 0, 0, 4, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 5, 0, 5, 0, 0, + 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 5, 0, 5, 0, 0, + 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 5, 0, 12, 0, 0, + 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 10, 5, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 10, + 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, + 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, + 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, + 9, 10, 9, 10, 9, 10, 9, 10, 10, 9, 10, 9, 10, 9, 10, 9, + 10, 9, 10, 9, 10, 9, 10, 9, 10, 10, 9, 10, 9, 10, 9, 10, + 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, + 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, + 9, 10, 9, 10, 9, 10, 9, 10, 9, 9, 10, 9, 10, 9, 10, 10, + 10, 9, 9, 10, 9, 10, 9, 9, 10, 9, 9, 9, 10, 10, 9, 9, + 9, 9, 10, 9, 9, 10, 9, 9, 9, 10, 10, 10, 9, 9, 10, 9, + 9, 10, 9, 10, 9, 10, 9, 9, 10, 9, 10, 10, 9, 10, 9, 9, + 10, 9, 9, 9, 10, 9, 10, 9, 9, 10, 10, 13, 9, 10, 10, 10, + 13, 13, 13, 13, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 10, 9, + 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 10, 9, 10, + 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, + 10, 9, 9, 10, 9, 10, 9, 9, 9, 10, 9, 10, 9, 10, 9, 10, + 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, + 9, 10, 9, 10, 10, 10, 10, 10, 10, 10, 9, 9, 10, 9, 9, 10, + 10, 9, 10, 9, 9, 9, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 13, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 13, 13, 13, 13, 13, 13, 13, + 10, 10, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 13, 0, 13, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 9, 10, 9, 10, 13, 0, 9, 10, 0, 0, 10, 10, 10, 10, 6, 9, + 0, 0, 0, 0, 0, 0, 9, 0, 9, 9, 9, 0, 9, 0, 9, 9, + 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, + 10, 10, 9, 9, 9, 10, 10, 10, 9, 10, 9, 10, 9, 10, 9, 10, + 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, + 10, 10, 10, 10, 9, 10, 0, 9, 10, 9, 9, 10, 10, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 9, 10, 0, 14, 14, 14, 14, 14, 14, 14, 9, 10, 9, 10, 9, 10, + 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, + 9, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 10, + 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, + 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 0, 0, 13, 0, 0, 0, 6, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 4, 0, 0, 0, 0, 0, 0, + 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 14, + 0, 14, 14, 0, 14, 14, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, 13, + 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 6, 6, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 12, 4, 4, 4, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 8, 8, 0, 13, 13, + 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 4, 13, 14, 14, 14, 14, 14, 14, 14, 8, 0, 14, + 14, 14, 14, 14, 14, 13, 13, 14, 14, 0, 14, 14, 14, 14, 13, 13, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 13, 13, 13, 0, 0, 13, + 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, + 13, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 13, 13, 0, 0, 6, 4, 13, 0, 0, 14, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 13, 14, 14, 14, 13, 14, 14, 14, 14, 14, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 4, 0, 4, 0, 0, 0, 4, 4, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 0, 13, 13, 13, 13, 13, 13, 0, + 8, 8, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 8, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 13, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 13, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 14, 14, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 14, 14, 14, 0, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 13, + 13, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 13, 13, 13, 13, 13, 13, + 13, 0, 13, 0, 0, 0, 13, 13, 13, 13, 0, 0, 14, 13, 14, 14, + 14, 14, 14, 14, 14, 0, 0, 14, 14, 0, 0, 14, 14, 14, 13, 0, + 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 13, 13, 0, 13, + 13, 13, 14, 14, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 14, 0, + 0, 14, 14, 14, 0, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, 13, + 13, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 13, 13, 13, 13, 13, 13, + 13, 0, 13, 13, 0, 13, 13, 0, 13, 13, 0, 0, 14, 0, 14, 14, + 14, 14, 14, 0, 0, 0, 0, 14, 14, 0, 0, 14, 14, 14, 0, 0, + 0, 14, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 0, 13, 0, + 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 14, 14, 13, 13, 13, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 14, 14, 14, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 13, + 13, 13, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 13, 13, 13, 13, 13, 13, + 13, 0, 13, 13, 0, 13, 13, 13, 13, 13, 0, 0, 14, 13, 14, 14, + 14, 14, 14, 14, 14, 14, 0, 14, 14, 14, 0, 14, 14, 14, 0, 0, + 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 14, 14, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 14, 14, 14, 14, 14, 14, + 0, 14, 14, 14, 0, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 13, + 13, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 14, 14, 14, 14, 14, 0, 0, 14, 14, 0, 0, 14, 14, 14, 0, 0, + 0, 0, 0, 0, 0, 14, 14, 14, 0, 0, 0, 0, 13, 13, 0, 13, + 13, 13, 14, 14, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 14, 13, 0, 13, 13, 13, 13, 13, 13, 0, 0, 0, 13, 13, + 13, 0, 13, 13, 13, 13, 0, 0, 0, 13, 13, 0, 13, 0, 13, 13, + 0, 0, 0, 13, 13, 0, 0, 0, 13, 13, 13, 0, 0, 0, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, 14, 14, + 14, 14, 14, 0, 0, 0, 14, 14, 14, 0, 14, 14, 14, 14, 0, 0, + 13, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 0, 13, 13, + 13, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 14, 13, 14, 14, + 14, 14, 14, 14, 14, 0, 14, 14, 14, 0, 14, 14, 14, 14, 0, 0, + 0, 0, 0, 0, 0, 14, 14, 0, 13, 13, 13, 0, 0, 13, 0, 0, + 13, 13, 14, 14, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 14, 14, 14, 0, 13, 13, 13, 13, 13, 13, 13, 13, 0, 13, 13, + 13, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 0, 13, 13, 13, 13, 13, 0, 0, 14, 13, 14, 14, + 14, 14, 14, 14, 14, 0, 14, 14, 14, 0, 14, 14, 14, 14, 0, 0, + 0, 0, 0, 0, 0, 14, 14, 0, 0, 0, 0, 0, 0, 13, 13, 0, + 13, 13, 14, 14, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 0, 13, 13, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 13, 13, + 13, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 13, 14, 14, + 14, 14, 14, 14, 14, 0, 14, 14, 14, 0, 14, 14, 14, 14, 13, 0, + 0, 0, 0, 0, 13, 13, 13, 14, 0, 0, 0, 0, 0, 0, 0, 13, + 13, 13, 14, 14, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, + 0, 14, 14, 14, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 13, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 14, 0, 0, 0, 0, 14, + 14, 14, 14, 14, 14, 0, 14, 0, 14, 14, 14, 14, 14, 14, 14, 14, + 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 0, 0, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 14, 13, 13, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 13, 13, 0, 13, 0, 13, 13, 13, 13, 13, 0, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 0, 13, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 14, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 0, 0, + 13, 13, 13, 13, 13, 0, 13, 0, 14, 14, 14, 14, 14, 14, 14, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 13, 13, 13, 13, + 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 0, 0, 0, 0, 0, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 14, 0, 14, 0, 14, 5, 5, 5, 5, 14, 14, + 13, 13, 13, 13, 13, 13, 13, 13, 0, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, + 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 0, 14, 14, 13, 13, 13, 13, 13, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 4, 4, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 13, 13, 13, 13, 14, 14, + 14, 13, 14, 14, 14, 13, 13, 14, 14, 14, 14, 14, 14, 14, 13, 13, + 13, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 14, 14, 14, 14, 0, 0, + 9, 9, 9, 9, 9, 9, 0, 9, 0, 0, 0, 0, 0, 9, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 10, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 13, 13, 13, 13, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 0, 13, 0, 13, 13, 13, 13, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 13, 13, 13, 13, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 0, 13, 13, 13, 13, 0, 0, 13, 13, 13, 13, 13, 13, 13, 0, + 13, 0, 13, 13, 13, 13, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 0, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 0, 13, 13, 13, 13, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 14, 14, 14, + 0, 0, 4, 0, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 0, 0, 10, 10, 10, 10, 10, 10, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 4, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 1, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 5, 5, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 14, 14, 14, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 13, 13, + 13, 0, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 4, 4, 0, 13, 0, 0, 0, 0, 13, 14, 0, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 6, 4, 0, 0, 0, 0, 6, 4, 0, 14, 14, 14, 12, 14, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 13, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, + 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 14, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 13, 4, 4, 4, 4, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 0, 4, 4, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 4, 4, 0, 0, 4, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, + 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 4, 4, 0, 0, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 13, 13, 13, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 4, 4, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 10, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 13, 13, 13, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 14, 13, 13, + 13, 13, 13, 13, 14, 13, 13, 14, 14, 14, 13, 0, 0, 0, 0, 0, + 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, + 9, 10, 9, 10, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, + 10, 10, 10, 10, 10, 10, 0, 0, 9, 9, 9, 9, 9, 9, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, + 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, + 10, 10, 10, 10, 10, 10, 0, 0, 9, 9, 9, 9, 9, 9, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 0, 9, 0, 9, 0, 9, 0, 9, + 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, + 10, 10, 10, 10, 10, 0, 10, 10, 9, 9, 9, 9, 9, 0, 10, 0, + 0, 0, 10, 10, 10, 0, 10, 10, 9, 9, 9, 9, 9, 0, 0, 0, + 10, 10, 10, 10, 0, 0, 10, 10, 9, 9, 9, 9, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 0, 0, 0, + 0, 0, 10, 10, 10, 0, 10, 10, 9, 9, 9, 9, 9, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 12, 14, 14, 12, 12, + 0, 0, 0, 6, 6, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, + 0, 0, 0, 0, 7, 0, 0, 0, 11, 11, 12, 12, 12, 12, 12, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 4, 4, 0, 0, + 0, 0, 0, 0, 0, 5, 5, 4, 4, 4, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 12, 12, 12, 12, 12, 0, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 10, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 9, 0, 0, 0, 0, 9, 0, 0, 10, 9, 9, 9, 10, 10, + 9, 9, 9, 10, 0, 9, 0, 0, 0, 9, 9, 9, 9, 9, 0, 0, + 0, 0, 0, 0, 9, 0, 9, 0, 9, 0, 9, 9, 9, 9, 0, 10, + 9, 9, 9, 9, 10, 13, 13, 13, 13, 10, 0, 0, 10, 10, 9, 9, + 0, 0, 0, 0, 0, 9, 10, 10, 10, 10, 0, 0, 0, 0, 10, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 9, 10, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, + 5, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, + 9, 10, 9, 9, 9, 10, 10, 9, 10, 9, 10, 9, 10, 9, 9, 9, + 9, 10, 9, 10, 10, 9, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, + 9, 10, 9, 10, 10, 0, 0, 0, 0, 0, 0, 9, 10, 9, 10, 14, + 14, 14, 9, 10, 0, 0, 0, 0, 0, 4, 4, 4, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 0, 10, 0, 0, 0, 0, 0, 10, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 13, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 0, 13, 13, 13, 13, 13, 13, 13, 0, + 13, 13, 13, 13, 13, 13, 13, 0, 13, 13, 13, 13, 13, 13, 13, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 4, 13, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, + 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, + 1, 6, 4, 0, 0, 13, 13, 13, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, + 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, + 0, 13, 13, 13, 13, 13, 0, 0, 13, 13, 13, 13, 13, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 0, 0, 14, 14, 0, 0, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 13, 13, 13, 13, + 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 4, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 4, 4, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 13, 13, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 13, 14, + 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 13, + 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, + 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 10, 10, 14, 14, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 14, 14, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 0, 0, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, + 10, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, + 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 10, 9, 10, 9, 9, 10, + 9, 10, 9, 10, 9, 10, 9, 10, 13, 0, 0, 9, 10, 9, 10, 13, + 9, 10, 9, 10, 10, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, + 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 9, 9, 9, 9, 10, + 9, 9, 9, 9, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, 9, 10, + 9, 10, 9, 10, 9, 9, 9, 9, 10, 9, 10, 9, 9, 10, 0, 0, + 9, 10, 0, 10, 0, 10, 9, 10, 9, 10, 9, 10, 9, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 9, 10, 13, 10, 10, 10, 13, 13, 13, 13, 13, + 13, 13, 14, 13, 13, 13, 14, 13, 13, 13, 13, 14, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 14, 14, 14, 14, 14, 0, 0, 0, 0, 14, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 13, 13, 13, 13, 13, 13, 0, 0, 0, 13, 0, 13, 13, 14, + 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 0, 4, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 13, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 13, 13, 13, 13, 13, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 14, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 0, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 4, 4, 4, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 13, 14, 14, 14, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 14, 13, 14, 14, 14, 13, 13, 14, 14, 13, 13, 13, 13, 13, 14, 14, + 13, 14, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, + 4, 4, 13, 13, 13, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 13, 13, 13, 13, 13, 13, 0, 0, 13, 13, 13, 13, 13, 13, 0, + 0, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 0, 13, 13, 13, 13, 13, 13, 13, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 4, 14, 14, 0, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 13, 14, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 0, 13, 13, 13, 13, 13, 0, 13, 0, + 13, 13, 0, 13, 13, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 5, 5, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 6, 6, 4, 6, 6, 4, 4, 5, 5, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 0, 6, 6, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 0, + 6, 6, 7, 0, 6, 6, 4, 4, 6, 5, 5, 5, 5, 5, 5, 0, + 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 12, + 0, 4, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, 6, 6, 7, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 6, 6, 0, 0, 0, 4, + 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 5, 0, 5, 0, 5, + 5, 4, 5, 5, 6, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, + 0, 0, 13, 13, 13, 13, 13, 13, 0, 0, 13, 13, 13, 13, 13, 13, + 0, 0, 13, 13, 13, 13, 13, 13, 0, 0, 13, 13, 13, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 12, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 0, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 13, 13, 0, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, + 13, 13, 13, 13, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, + 0, 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, + 9, 9, 9, 0, 9, 9, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 13, 13, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 0, 0, 13, 0, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 0, 13, 13, 0, 0, 0, 13, 0, 0, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 0, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 13, 13, + 13, 14, 14, 14, 0, 14, 14, 0, 0, 0, 0, 0, 14, 14, 14, 14, + 13, 13, 13, 13, 0, 13, 13, 13, 0, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 0, 0, 14, 14, 14, 0, 0, 0, 0, 14, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 13, 13, 13, 13, 13, 13, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 0, 0, 0, 14, 14, 14, 14, 14, 0, 13, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 14, 14, 0, 0, 0, + 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, + 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 0, 0, 0, 0, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, + 13, 13, 14, 14, 14, 14, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 4, 4, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 14, 13, 13, 14, 14, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 8, 4, 4, + 4, 4, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 0, 4, 4, 4, 13, 14, 14, 13, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 14, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 13, 13, 13, 13, 4, 4, 0, 0, 14, 14, 14, 14, 4, 14, 14, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 13, 0, 13, 0, 4, 4, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 4, 4, 0, 4, 4, 0, 14, 13, + 13, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 0, 13, 0, 13, 13, 13, 13, 0, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 4, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 0, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 13, + 13, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 13, 13, 13, 13, 13, 13, + 13, 0, 13, 13, 0, 13, 13, 13, 13, 13, 0, 14, 14, 13, 14, 14, + 14, 14, 14, 14, 14, 0, 0, 14, 14, 0, 0, 14, 14, 14, 0, 0, + 13, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 13, 13, 13, + 13, 13, 14, 14, 0, 0, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, + 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 13, 0, 0, 13, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 0, 13, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 0, 14, 0, 0, 14, 0, 14, 14, 14, 14, 0, 14, 14, 14, 14, + 14, 13, 14, 13, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 4, 4, 0, 0, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 14, 13, + 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 13, 13, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, + 14, 14, 14, 14, 14, 14, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 0, 4, 4, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 13, 13, 13, 13, 14, 14, 0, 0, + 14, 4, 4, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 13, 0, 0, 0, 0, 0, 0, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 4, 4, 4, 0, + 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, + 13, 13, 13, 13, 13, 13, 13, 0, 0, 13, 0, 0, 13, 13, 13, 13, + 13, 13, 13, 13, 0, 13, 13, 0, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 14, 14, 14, 14, 14, 14, 0, 14, 14, 0, 0, 14, 14, 14, 14, 13, + 14, 13, 14, 14, 4, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 14, 14, 14, 14, 14, 14, 14, 0, 0, 14, 14, 14, 14, 14, 14, + 14, 13, 0, 13, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 0, + 0, 0, 4, 4, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 4, 4, 13, 0, 0, + 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, + 14, 14, 14, 14, 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, 14, + 13, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 0, 13, 13, 0, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 14, 14, 14, 14, 14, 14, 0, 0, 0, 14, 0, 14, 14, 0, 14, + 14, 14, 14, 14, 14, 14, 13, 14, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 0, 13, 13, 0, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 0, + 14, 14, 0, 14, 14, 14, 14, 14, 13, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 14, 14, 14, 14, 4, 4, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 13, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 14, 14, + 14, 14, 14, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 14, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 14, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 4, 4, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, + 14, 14, 14, 14, 14, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 14, 14, 14, 14, 14, 14, 14, 4, 4, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 4, 4, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, 14, + 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 14, + 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 0, 13, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 0, 13, 13, 13, 13, 13, 13, 13, 0, 13, 13, 0, + 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 14, 14, 4, + 12, 12, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 0, 0, 0, 14, 14, 14, + 14, 14, 14, 12, 12, 12, 12, 12, 12, 12, 12, 14, 14, 14, 14, 14, + 14, 14, 14, 0, 0, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, + 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 0, 9, 9, + 0, 0, 9, 0, 0, 9, 9, 0, 0, 9, 9, 9, 9, 0, 9, 9, + 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 0, 10, 0, 10, 10, 10, + 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 9, 9, 0, 9, 9, 9, 9, 0, 0, 9, 9, 9, + 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 0, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 0, 9, 9, 9, 9, 0, + 9, 9, 9, 9, 9, 0, 9, 0, 0, 0, 9, 9, 9, 9, 9, 9, + 9, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 10, 10, 10, 10, 10, 10, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, + 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, + 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 9, 10, 0, 0, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, + 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 14, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, + 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 13, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, + 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 14, 14, 14, 14, 14, + 14, 14, 0, 14, 14, 0, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 0, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 13, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, + 13, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 0, 13, 13, 13, 13, 0, 13, 13, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, + 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 14, 14, 14, 14, 14, 14, 14, 13, 0, 0, 0, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 0, 13, 13, 0, 13, 0, 0, 13, 0, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 0, 13, 13, 13, 13, 0, 13, 0, 13, 0, 0, 0, 0, + 0, 0, 13, 0, 0, 0, 0, 13, 0, 13, 0, 13, 0, 13, 13, 13, + 0, 13, 13, 0, 13, 0, 0, 13, 0, 13, 0, 13, 0, 13, 0, 13, + 0, 13, 13, 0, 13, 0, 0, 13, 13, 13, 13, 0, 13, 13, 13, 13, + 13, 13, 13, 0, 13, 13, 13, 13, 0, 13, 13, 13, 13, 0, 13, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, + 0, 13, 13, 13, 0, 13, 13, 13, 13, 13, 0, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +RE_UINT32 re_get_sentence_break(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = codepoint & 0x1F; + + v = re_sentence_break_table_1[field_2]; + v = re_sentence_break_table_2[(v << 5) | field_1]; + v = re_sentence_break_table_3[(v << 5) | field_0]; + + return v; +} + +/* Sentence_Terminal. */ +static RE_UINT8 re_sentence_terminal_table_1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 3, 3, 9, 10, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 11, 12, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 13, + 3, 3, 14, 15, 16, 17, 18, 19, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 20, 21, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 22, + 3, 3, 3, 3, 3, 3, 23, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 +}; + +static RE_UINT8 re_sentence_terminal_table_2[] = { + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 3, 0, 0, 0, 0, 0, 4, 0, 5, 0, 0, 0, 0, 0, 0, 6, + 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 11, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 13, 0, + 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 16, 3, 0, 0, 0, 0, + 0, 17, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 19, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 22, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, + 26, 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 28, 0, 0, 26, 0, 0, 29, 0, 0, 0, 0, 30, 0, + 0, 0, 3, 0, 0, 0, 0, 31, 0, 0, 0, 0, 0, 0, 0, 32, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 33, 0, 34, 0, 0, 0, 0, 0, 1, 0, 0, 35, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 37, 0, 0, 0, + 0, 0, 38, 0, 0, 18, 39, 0, 0, 0, 40, 0, 0, 0, 41, 0, + 0, 42, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, + 0, 0, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 0, + 0, 0, 45, 0, 0, 0, 0, 0, 0, 46, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, + 0, 0, 48, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 49, 0, 0, 50, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 26, 0, 0, 0, 51, 0, 49, 52, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 0, 0, 0, 0, + 0, 0, 0, 0, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_sentence_terminal_table_3[] = { + 0, 0, 0, 0, 2, 64, 0, 128, 0, 2, 0, 0, 0, 0, 0, 224, + 0, 0, 16, 0, 7, 0, 0, 0, 0, 0, 0, 2, 0, 0, 128, 98, + 48, 0, 0, 0, 0, 12, 0, 0, 132, 1, 0, 0, 0, 64, 0, 0, + 0, 0, 96, 0, 0, 0, 48, 0, 8, 2, 0, 0, 0, 15, 0, 0, + 0, 192, 0, 204, 0, 0, 0, 24, 0, 0, 0, 192, 16, 0, 0, 48, + 128, 3, 0, 0, 0, 0, 0, 14, 0, 64, 0, 16, 0, 0, 24, 0, + 4, 0, 0, 0, 0, 0, 0, 128, 0, 192, 0, 0, 0, 0, 136, 0, + 0, 0, 192, 0, 0, 128, 0, 0, 0, 3, 0, 0, 0, 0, 3, 0, + 0, 8, 0, 0, 0, 0, 100, 0, 0, 0, 196, 0, 2, 0, 0, 0, + 0, 0, 224, 3, 192, 3, 0, 0, 128, 1, 0, 0, 3, 0, 0, 0, + 14, 0, 0, 0, 96, 32, 0, 192, 0, 0, 0, 27, 0, 24, 0, 0, + 12, 254, 255, 0, 6, 0, 0, 0, 0, 0, 0, 112, 80, 0, 0, 0, + 12, 0, 0, 0, 0, 0, 128, 1, 24, 0, 0, 0, 0, 0, 32, 0, + 16, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0 +}; + +RE_UINT32 re_get_sentence_terminal(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_sentence_terminal_table_1[field_2]; + v = re_sentence_terminal_table_2[(v << 5) | field_1]; + v = re_sentence_terminal_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Soft_Dotted. */ +static RE_UINT8 re_soft_dotted_table_1[] = { + 0, 1, 2, 2, 2, 2, 2, 3, 4, 2, 2, 5, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 6, 2, 7, 8, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 +}; + +static RE_UINT8 re_soft_dotted_table_2[] = { + 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 4, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, + 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 10, 11, 0, 0, + 0, 12, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 17, 18, 0, 19, 20, 0, 21, 0, 22, 23, 0, 24, 0, 17, 18, + 0, 19, 20, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 26, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_soft_dotted_table_3[] = { + 0, 0, 0, 0, 0, 6, 0, 0, 0, 128, 0, 0, 0, 2, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 32, 0, 0, 4, 0, 0, 0, 8, 0, + 0, 0, 64, 1, 4, 0, 0, 0, 0, 0, 64, 0, 16, 1, 0, 0, + 0, 32, 0, 0, 0, 8, 0, 0, 0, 0, 2, 0, 0, 3, 0, 0, + 0, 0, 0, 16, 12, 0, 0, 0, 0, 0, 192, 0, 0, 12, 0, 0, + 0, 0, 0, 192, 0, 0, 12, 0, 192, 0, 0, 0, 0, 0, 0, 12, + 0, 192, 0, 0, 0, 0, 0, 4, 0, 48, 0, 0 +}; + +RE_UINT32 re_get_soft_dotted(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_soft_dotted_table_1[field_2]; + v = re_soft_dotted_table_2[(v << 5) | field_1]; + v = re_soft_dotted_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Terminal_Punctuation. */ +static RE_UINT8 re_terminal_punctuation_table_1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 11, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 12, 13, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 14, + 15, 9, 16, 17, 18, 19, 20, 21, 9, 22, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 23, 24, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 25, + 9, 9, 9, 9, 9, 9, 26, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 +}; + +static RE_UINT8 re_terminal_punctuation_table_2[] = { + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 5, 0, + 6, 0, 0, 0, 0, 0, 7, 0, 8, 0, 0, 0, 0, 0, 0, 9, + 0, 10, 2, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 12, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 16, 0, 0, 0, 17, 0, 18, 0, 0, 0, 0, 19, 0, + 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 22, 23, 0, 0, 0, 0, + 0, 24, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 26, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 29, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, + 32, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 34, 0, 0, 35, 0, 0, 36, 0, 0, 0, 0, 27, 0, + 0, 0, 23, 0, 0, 0, 37, 38, 0, 0, 0, 0, 0, 0, 0, 39, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 40, 0, 41, 0, 0, 0, 0, 0, 1, 0, 0, 42, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 0, 43, 0, + 0, 0, 44, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 34, 0, 0, 0, 0, 45, 0, 46, 0, 0, 47, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 49, 0, 0, 0, + 0, 0, 50, 0, 0, 25, 51, 0, 0, 0, 52, 0, 0, 0, 53, 0, + 0, 54, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 55, 0, + 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 0, + 0, 0, 31, 0, 0, 0, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 0, 0, 0, 0, 0, + 0, 0, 60, 0, 61, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 52, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 64, 0, 0, 0, 0, 0, + 0, 0, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 35, 0, 0, 0, 66, 0, 67, 68, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 0, 0, 0, 0, + 0, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 69, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_terminal_punctuation_table_3[] = { + 0, 0, 0, 0, 2, 80, 0, 140, 0, 0, 0, 64, 128, 0, 0, 0, + 0, 2, 0, 0, 8, 0, 0, 0, 0, 16, 0, 232, 0, 0, 16, 0, + 255, 23, 0, 0, 0, 0, 0, 3, 0, 0, 191, 127, 48, 0, 0, 0, + 0, 0, 0, 12, 0, 225, 7, 0, 0, 12, 0, 0, 254, 1, 0, 0, + 0, 64, 0, 0, 0, 56, 0, 0, 0, 0, 96, 0, 0, 0, 112, 4, + 60, 3, 0, 0, 0, 15, 0, 0, 0, 192, 0, 236, 0, 0, 0, 224, + 0, 0, 0, 248, 0, 0, 0, 192, 16, 0, 0, 48, 128, 3, 0, 0, + 0, 0, 0, 14, 0, 64, 0, 16, 2, 208, 24, 0, 6, 0, 0, 0, + 0, 224, 0, 0, 0, 0, 248, 0, 0, 0, 192, 0, 0, 192, 0, 0, + 0, 128, 0, 0, 0, 0, 0, 128, 0, 0, 3, 0, 0, 8, 0, 0, + 0, 0, 100, 0, 0, 0, 247, 0, 18, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 128, 0, 0, 0, 63, 0, 0, 0, 0, 252, 0, 0, 0, 30, + 0, 0, 224, 3, 192, 3, 0, 0, 128, 63, 0, 0, 3, 0, 0, 0, + 14, 0, 0, 0, 96, 32, 0, 192, 0, 0, 0, 31, 0, 0, 48, 0, + 0, 56, 0, 12, 60, 254, 255, 0, 0, 0, 0, 112, 80, 0, 0, 0, + 12, 0, 0, 0, 0, 0, 0, 24, 0, 0, 2, 0, 0, 0, 128, 1, + 24, 0, 0, 0, 0, 0, 31, 0, 0, 0, 32, 0, 0, 0, 128, 3, + 16, 0, 0, 0, 128, 7, 0, 0 +}; + +RE_UINT32 re_get_terminal_punctuation(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_terminal_punctuation_table_1[field_2]; + v = re_terminal_punctuation_table_2[(v << 5) | field_1]; + v = re_terminal_punctuation_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Unified_Ideograph. */ +static RE_UINT8 re_unified_ideograph_table_1[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, + 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 5, 6, 1, + 1, 1, 1, 7, 1, 1, 1, 1, 1, 1, 8, 9, 0, 0, 0, 0, + 1, 1, 1, 1, 10, 1, 1, 1, 11, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_unified_ideograph_table_2[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 1, 1, + 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 7, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 8, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 0, 0 +}; + +static RE_UINT8 re_unified_ideograph_table_3[] = { + 0, 0, 0, 0, 255, 255, 255, 255, 0, 192, 26, 128, 154, 3, 0, 0, + 255, 255, 255, 3, 255, 255, 255, 63, 3, 0, 255, 255, 1, 0, 255, 255, + 255, 7, 255, 255, 255, 255, 0, 0 +}; + +RE_UINT32 re_get_unified_ideograph(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_unified_ideograph_table_1[field_2]; + v = re_unified_ideograph_table_2[(v << 5) | field_1]; + v = re_unified_ideograph_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Uppercase. */ +static RE_UINT8 re_uppercase_table_1[] = { + 0, 1, 2, 2, 3, 2, 2, 4, 5, 6, 2, 7, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 8, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, + 2, 10, 2, 11, 2, 2, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 13, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 14, 2, 2, 2, 2, 15, 2, 16, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 +}; + +static RE_UINT8 re_uppercase_table_2[] = { + 0, 0, 1, 0, 0, 0, 2, 0, 3, 4, 5, 6, 7, 8, 9, 10, + 3, 11, 12, 0, 0, 0, 0, 0, 0, 0, 0, 13, 14, 15, 16, 17, + 18, 19, 0, 3, 20, 3, 21, 3, 3, 22, 23, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 18, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 25, + 0, 0, 0, 0, 26, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 3, 3, 3, 28, 3, 3, 3, 29, 30, 31, 32, 0, 33, 34, 35, + 0, 0, 0, 0, 0, 0, 0, 0, 36, 37, 38, 19, 39, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 40, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 18, 19, 0, 41, 3, 3, 3, 42, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 43, 44, 0, 0, 0, 0, 45, 3, 46, 47, 48, 49, 50, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 18, 51, 0, 0, 0, 52, 53, 0, 0, 0, 0, 54, 55, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 18, 56, 0, 0, 0, 0, 52, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 58, 59, 60, 61, 62, 63, 52, 64, 65, 66, 67, 68, 57, 58, 59, 60, + 61, 69, 25, 52, 64, 61, 70, 71, 72, 73, 40, 74, 52, 75, 76, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 18, 77, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 78, 78, 64, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_uppercase_table_3[] = { + 0, 0, 0, 0, 254, 255, 255, 7, 255, 255, 127, 127, 85, 85, 85, 85, + 85, 85, 85, 170, 170, 84, 85, 85, 85, 85, 85, 43, 214, 206, 219, 177, + 213, 210, 174, 17, 144, 164, 170, 74, 85, 85, 210, 85, 85, 85, 5, 108, + 122, 85, 0, 0, 0, 0, 69, 128, 64, 215, 254, 255, 251, 15, 0, 0, + 0, 128, 28, 85, 85, 85, 144, 230, 255, 255, 255, 255, 255, 255, 0, 0, + 1, 84, 85, 85, 171, 42, 85, 85, 85, 85, 254, 255, 255, 255, 127, 0, + 191, 32, 0, 0, 255, 255, 63, 0, 0, 2, 255, 255, 255, 255, 255, 231, + 85, 85, 21, 64, 0, 255, 0, 63, 0, 255, 0, 255, 0, 63, 0, 170, + 0, 255, 0, 0, 0, 0, 0, 15, 0, 15, 0, 15, 0, 31, 0, 15, + 132, 56, 39, 62, 80, 61, 15, 192, 32, 0, 0, 0, 8, 0, 0, 0, + 0, 0, 192, 255, 157, 234, 37, 192, 5, 40, 4, 0, 85, 21, 0, 0, + 85, 85, 85, 5, 84, 85, 84, 85, 85, 85, 0, 106, 85, 40, 69, 85, + 85, 125, 95, 85, 245, 26, 65, 21, 0, 0, 32, 0, 255, 0, 0, 0, + 0, 0, 255, 255, 255, 255, 15, 0, 0, 0, 255, 247, 255, 247, 55, 0, + 255, 255, 7, 0, 63, 0, 0, 0, 255, 255, 255, 3, 0, 0, 240, 255, + 255, 63, 0, 0, 0, 255, 255, 255, 3, 0, 0, 208, 100, 222, 63, 0, + 255, 3, 0, 0, 176, 231, 223, 31, 0, 0, 0, 123, 95, 252, 1, 0, + 0, 240, 255, 255, 3, 0, 0, 240, 1, 0, 0, 0, 252, 255, 255, 7, + 0, 0, 0, 240, 255, 255, 31, 0, 255, 127, 0, 0, 255, 1, 0, 0, + 0, 4, 0, 0, 3, 0, 0, 0, 255, 3, 255, 255 +}; + +RE_UINT32 re_get_uppercase(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_uppercase_table_1[field_2]; + v = re_uppercase_table_2[(v << 5) | field_1]; + v = re_uppercase_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Variation_Selector. */ +RE_UINT32 re_get_variation_selector(RE_UINT32 codepoint) { + if (0x180B <= codepoint && codepoint <= 0x180D) + return 1; + if (codepoint == 0x180F) + return 1; + if (0xFE00 <= codepoint && codepoint <= 0xFE0F) + return 1; + if (0x0E0100 <= codepoint && codepoint <= 0x0E01EF) + return 1; + + return 0; +} + +/* Vert_Space. */ +RE_UINT32 re_get_vert_space(RE_UINT32 codepoint) { + if (0x0A <= codepoint && codepoint <= 0x0D) + return 1; + if (codepoint == 0x85) + return 1; + if (0x2028 <= codepoint && codepoint <= 0x2029) + return 1; + + return 0; +} + +/* White_Space. */ +static RE_UINT8 re_white_space_table_1[] = { + 0, 1, 1, 1, 1, 2, 1, 1, 3, 1, 1, 1, 4, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +}; + +static RE_UINT8 re_white_space_table_2[] = { + 0, 1, 2, 2, 3, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 4, 5, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 +}; + +static RE_UINT8 re_white_space_table_3[] = { + 0, 62, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, + 255, 7, 0, 0, 0, 131, 0, 0, 0, 0, 0, 128 +}; + +RE_UINT32 re_get_white_space(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_white_space_table_1[field_2]; + v = re_white_space_table_2[(v << 5) | field_1]; + v = re_white_space_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Word. */ +static RE_UINT8 re_word_table_1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 13, + 13, 13, 13, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 15, 16, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 17, 10, 10, 10, 10, 10, 10, 10, 10, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 10, 30, 13, 31, 13, 13, + 32, 33, 10, 10, 10, 10, 10, 10, 34, 10, 35, 36, 13, 13, 13, 13, + 13, 37, 13, 38, 10, 10, 10, 10, 10, 10, 10, 39, 40, 10, 10, 41, + 10, 10, 10, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 10, 52, 10, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 53, 13, 13, 13, 54, 55, 13, + 13, 13, 13, 56, 13, 13, 13, 13, 13, 13, 57, 58, 10, 10, 59, 10, + 13, 13, 13, 13, 60, 13, 13, 13, 61, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 62, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 +}; + +static RE_UINT16 re_word_table_2[] = { + 0, 1, 2, 3, 0, 4, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 7, 8, 6, 6, 6, 9, 10, 11, 6, 12, + 6, 6, 6, 6, 11, 6, 6, 6, 6, 13, 14, 6, 15, 16, 17, 18, + 19, 6, 6, 20, 6, 6, 21, 22, 23, 6, 24, 6, 6, 25, 6, 26, + 6, 27, 28, 29, 30, 6, 6, 11, 6, 6, 6, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, 44, 41, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 51, 6, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 0, 68, 69, 70, 0, 71, 72, 73, 74, 75, 76, 77, 0, + 6, 6, 78, 6, 79, 6, 80, 81, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 82, 6, 83, 84, 85, 6, 86, 6, 87, 0, 88, 6, 6, 89, + 65, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 90, 3, 6, 6, 91, 92, 93, 94, 95, 6, 6, 96, 97, + 98, 6, 6, 99, 6, 29, 6, 100, 101, 102, 103, 104, 6, 105, 106, 0, + 28, 6, 101, 107, 106, 108, 109, 0, 6, 6, 110, 111, 6, 6, 6, 94, + 6, 112, 113, 79, 29, 87, 114, 66, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 89, 6, 115, 79, 6, 116, 117, 118, + 119, 120, 121, 122, 123, 0, 23, 124, 125, 126, 127, 6, 128, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 129, 6, 97, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 6, 6, 6, 6, 6, 6, 130, 6, 80, 6, 131, 132, 133, 133, 6, + 0, 134, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 135, 136, 65, 6, 137, 65, 6, 81, 138, 13, 6, 6, 109, 6, 0, 23, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 0, 0, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 139, 0, 23, 79, 6, 6, 6, 6, 6, 6, 6, 6, + 140, 141, 6, 142, 6, 6, 6, 25, 143, 144, 6, 6, 145, 6, 146, 147, + 6, 148, 6, 94, 6, 6, 149, 150, 6, 151, 94, 76, 6, 6, 152, 101, + 6, 132, 153, 154, 6, 6, 155, 156, 157, 158, 81, 78, 6, 6, 6, 159, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 160, 161, 28, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 151, 6, 6, 162, 0, 163, 164, 165, 6, 6, 25, 166, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 79, 23, 6, 167, 6, 168, 169, + 88, 170, 171, 172, 6, 6, 6, 76, 1, 2, 3, 103, 6, 101, 173, 0, + 174, 175, 176, 0, 6, 6, 6, 66, 0, 0, 6, 93, 0, 0, 0, 177, + 0, 0, 0, 0, 76, 6, 124, 178, 6, 179, 29, 66, 79, 6, 180, 0, + 6, 6, 6, 6, 79, 78, 181, 28, 6, 182, 6, 183, 184, 185, 6, 94, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 132, 100, 168, 186, 187, 0, 0, + 188, 189, 100, 132, 101, 0, 0, 190, 100, 162, 0, 0, 6, 191, 0, 0, + 192, 193, 0, 76, 76, 0, 73, 194, 6, 100, 100, 195, 25, 0, 0, 0, + 6, 6, 128, 0, 6, 195, 6, 195, 6, 196, 6, 197, 198, 0, 0, 0, + 0, 0, 0, 0, 6, 199, 200, 201, 76, 108, 124, 23, 198, 23, 202, 132, + 6, 6, 194, 203, 6, 66, 204, 205, 6, 206, 207, 208, 6, 6, 209, 0, + 210, 191, 211, 0, 212, 213, 6, 214, 32, 215, 216, 217, 218, 12, 219, 220, + 6, 6, 221, 211, 6, 6, 222, 0, 0, 0, 0, 0, 6, 223, 224, 0, + 6, 6, 225, 0, 6, 99, 78, 226, 87, 227, 194, 0, 0, 0, 0, 0, + 6, 66, 0, 0, 0, 6, 6, 228, 229, 230, 231, 0, 0, 232, 233, 234, + 6, 101, 108, 6, 235, 23, 6, 99, 0, 0, 0, 0, 0, 0, 6, 236, + 237, 5, 236, 147, 167, 238, 0, 0, 239, 240, 196, 241, 242, 97, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 132, 243, 244, 245, 0, 0, 246, 0, 0, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 162, 0, 0, 0, + 6, 6, 6, 109, 6, 6, 6, 6, 6, 6, 226, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 6, 6, 124, + 6, 88, 100, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 66, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 162, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 99, 101, 78, 6, 101, 78, 104, 6, 132, 231, 247, 88, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 110, 0, 0, 0, 0, + 0, 0, 6, 6, 0, 0, 0, 0, 6, 6, 248, 6, 249, 0, 0, 250, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 112, + 6, 6, 6, 6, 6, 6, 100, 120, 128, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 252, 253, 207, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 28, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 6, 6, 254, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 151, 194, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 256, 257, 258, 0, 0, + 0, 0, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 6, 206, 6, 259, 260, 261, 6, 262, 263, 264, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 265, 266, 81, 206, 206, 267, 267, 237, 237, 268, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 269, 6, 270, 271, 272, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 101, 273, 0, 0, 0, 0, 0, 0, + 274, 275, 6, 27, 134, 0, 0, 0, 6, 276, 277, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 23, 109, 6, 162, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 23, 162, 0, 0, 0, 0, 0, 0, 23, 66, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 278, + 6, 6, 6, 6, 6, 6, 279, 0, 6, 6, 227, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 261, 280, 281, 282, 283, 284, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 78, 78, 97, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 0, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 162, 6, 6, 6, 6, 6, 6, + 79, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 285, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 286, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 29, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 88, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, 88, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_word_table_3[] = { + 0, 0, 0, 0, 0, 0, 255, 3, 254, 255, 255, 135, 254, 255, 255, 7, + 0, 4, 32, 4, 255, 255, 127, 255, 255, 255, 255, 255, 195, 255, 3, 0, + 31, 80, 0, 0, 255, 255, 223, 188, 64, 215, 255, 255, 251, 255, 255, 255, + 255, 255, 191, 255, 255, 255, 254, 255, 255, 255, 127, 2, 255, 1, 254, 255, + 255, 255, 255, 191, 182, 0, 255, 255, 255, 135, 7, 0, 0, 0, 255, 7, + 255, 195, 255, 255, 255, 255, 239, 159, 255, 253, 255, 159, 0, 0, 255, 255, + 255, 231, 255, 255, 255, 255, 3, 0, 255, 255, 63, 36, 255, 63, 0, 0, + 255, 255, 255, 15, 255, 7, 255, 255, 255, 126, 128, 255, 207, 255, 254, 255, + 239, 159, 249, 255, 255, 253, 197, 243, 159, 121, 128, 176, 207, 255, 3, 80, + 238, 135, 249, 255, 255, 253, 109, 211, 135, 57, 2, 94, 192, 255, 63, 0, + 238, 191, 251, 255, 255, 253, 237, 243, 191, 59, 1, 0, 207, 255, 0, 254, + 238, 159, 249, 255, 159, 57, 224, 176, 207, 255, 2, 0, 236, 199, 61, 214, + 24, 199, 255, 195, 199, 61, 129, 0, 192, 255, 0, 0, 255, 223, 253, 255, + 255, 253, 255, 243, 223, 61, 96, 39, 207, 255, 0, 0, 239, 223, 253, 255, + 255, 253, 239, 243, 223, 61, 96, 96, 207, 255, 14, 0, 223, 125, 240, 128, + 207, 255, 0, 252, 238, 255, 127, 252, 255, 255, 251, 47, 127, 132, 95, 255, + 192, 255, 12, 0, 254, 255, 255, 255, 255, 255, 255, 7, 255, 127, 255, 3, + 214, 247, 255, 255, 175, 255, 255, 63, 95, 127, 255, 243, 1, 0, 0, 3, + 255, 3, 160, 194, 255, 254, 255, 255, 255, 31, 254, 255, 223, 255, 255, 254, + 255, 255, 255, 31, 64, 0, 0, 0, 255, 3, 255, 255, 255, 255, 255, 63, + 191, 32, 255, 255, 255, 255, 255, 247, 255, 61, 127, 61, 255, 61, 255, 255, + 255, 255, 61, 127, 61, 255, 127, 255, 255, 255, 61, 255, 255, 255, 255, 231, + 255, 255, 0, 0, 255, 255, 63, 63, 255, 159, 255, 255, 255, 199, 255, 1, + 255, 255, 63, 128, 255, 255, 31, 0, 255, 255, 15, 0, 255, 223, 13, 0, + 255, 255, 143, 48, 255, 3, 0, 0, 0, 184, 255, 3, 255, 255, 255, 1, + 255, 255, 63, 0, 255, 255, 255, 127, 255, 15, 255, 15, 192, 255, 255, 255, + 255, 63, 31, 0, 255, 15, 255, 255, 255, 3, 255, 3, 255, 255, 255, 159, + 128, 0, 255, 255, 255, 127, 0, 0, 255, 31, 255, 3, 0, 248, 15, 0, + 255, 255, 255, 0, 255, 227, 255, 255, 0, 0, 247, 255, 63, 63, 255, 170, + 255, 255, 223, 95, 220, 31, 207, 15, 255, 31, 220, 31, 0, 48, 0, 0, + 0, 0, 0, 128, 1, 0, 16, 0, 0, 0, 2, 128, 0, 0, 255, 31, + 255, 255, 1, 0, 132, 252, 47, 62, 80, 189, 255, 243, 224, 67, 0, 0, + 255, 1, 0, 0, 0, 0, 192, 255, 31, 248, 15, 0, 255, 128, 0, 128, + 255, 255, 127, 0, 127, 127, 127, 127, 0, 128, 0, 0, 224, 0, 0, 0, + 254, 255, 62, 31, 255, 255, 127, 230, 224, 255, 255, 255, 255, 31, 0, 0, + 255, 31, 255, 255, 255, 15, 0, 0, 255, 255, 247, 191, 0, 0, 128, 255, + 252, 255, 255, 255, 255, 249, 255, 255, 255, 63, 235, 31, 0, 0, 252, 255, + 255, 16, 0, 0, 63, 0, 255, 3, 255, 255, 255, 232, 255, 63, 255, 255, + 1, 128, 255, 3, 255, 63, 255, 3, 255, 255, 127, 252, 7, 0, 0, 56, + 255, 255, 124, 0, 126, 126, 126, 0, 127, 127, 255, 255, 255, 55, 255, 3, + 15, 0, 255, 255, 127, 248, 255, 255, 255, 255, 255, 3, 127, 0, 248, 224, + 255, 253, 127, 95, 219, 255, 255, 255, 0, 0, 248, 255, 255, 255, 252, 255, + 255, 0, 0, 0, 0, 0, 255, 15, 255, 255, 24, 0, 0, 224, 0, 0, + 0, 0, 223, 255, 252, 252, 252, 28, 255, 239, 255, 255, 127, 255, 255, 183, + 255, 63, 255, 63, 0, 0, 0, 32, 1, 0, 0, 0, 0, 224, 255, 255, + 15, 255, 62, 0, 255, 255, 15, 255, 255, 0, 255, 255, 15, 0, 255, 247, + 255, 247, 183, 255, 251, 255, 251, 27, 191, 255, 255, 255, 255, 255, 253, 7, + 63, 253, 255, 255, 255, 255, 191, 145, 255, 255, 55, 0, 255, 255, 255, 192, + 111, 240, 239, 254, 255, 255, 63, 135, 127, 0, 0, 0, 255, 255, 7, 0, + 255, 0, 255, 3, 63, 190, 255, 255, 63, 0, 0, 0, 255, 27, 3, 0, + 28, 0, 0, 0, 0, 0, 0, 240, 31, 0, 0, 0, 192, 255, 63, 128, + 4, 0, 255, 255, 255, 1, 255, 3, 255, 255, 223, 255, 240, 0, 255, 255, + 255, 255, 79, 0, 31, 222, 255, 23, 255, 255, 251, 255, 3, 0, 0, 0, + 127, 189, 255, 191, 255, 1, 255, 255, 255, 7, 255, 3, 255, 253, 237, 251, + 159, 57, 129, 224, 207, 31, 31, 0, 255, 75, 255, 255, 165, 247, 15, 0, + 6, 0, 0, 0, 255, 7, 255, 195, 191, 0, 255, 3, 255, 255, 63, 255, + 1, 0, 0, 63, 17, 0, 255, 3, 15, 0, 0, 0, 255, 15, 255, 3, + 255, 3, 0, 128, 127, 242, 111, 255, 255, 255, 191, 249, 15, 0, 255, 3, + 255, 252, 255, 255, 255, 255, 255, 252, 27, 0, 0, 0, 255, 255, 255, 35, + 1, 0, 255, 3, 255, 253, 255, 255, 255, 254, 127, 0, 127, 251, 255, 255, + 255, 255, 127, 180, 191, 253, 255, 255, 255, 127, 251, 1, 255, 255, 253, 255, + 255, 255, 255, 199, 7, 0, 255, 7, 0, 0, 1, 0, 248, 255, 255, 224, + 255, 135, 255, 255, 255, 128, 255, 255, 27, 0, 3, 0, 0, 0, 239, 111, + 7, 0, 4, 0, 0, 0, 39, 0, 255, 7, 255, 31, 255, 1, 255, 99, + 224, 227, 7, 248, 231, 15, 0, 0, 0, 60, 0, 0, 255, 255, 255, 223, + 100, 222, 255, 235, 239, 255, 255, 255, 191, 231, 223, 223, 255, 255, 255, 123, + 95, 252, 253, 255, 63, 255, 255, 255, 253, 255, 255, 247, 255, 127, 255, 255, + 247, 207, 255, 255, 255, 255, 127, 248, 255, 31, 32, 0, 16, 0, 0, 248, + 254, 255, 0, 0, 224, 7, 0, 0, 127, 255, 255, 249, 219, 7, 255, 255, + 255, 31, 255, 63, 255, 67, 0, 0, 127, 111, 255, 127, 31, 0, 127, 0, + 150, 254, 247, 10, 132, 234, 150, 170, 150, 247, 247, 94, 255, 251, 255, 15, + 238, 251, 255, 15, 3, 0, 255, 255, 1, 0, 255, 255 +}; + +RE_UINT32 re_get_word(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_word_table_1[field_2]; + v = re_word_table_2[(v << 5) | field_1]; + v = re_word_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* Word_Break. */ +static RE_UINT8 re_word_break_table_1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 13, 14, 15, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 16, 10, 10, 10, 10, 10, 10, 10, 10, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 10, 29, 13, 30, 13, 13, + 31, 32, 10, 10, 10, 10, 10, 10, 33, 10, 34, 35, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 36, 37, 10, 10, 38, + 10, 10, 10, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 10, 49, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 50, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 +}; + +static RE_UINT16 re_word_break_table_2[] = { + 0, 1, 2, 3, 4, 5, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 8, 7, 9, 9, 9, 10, 11, 12, 7, 13, + 7, 7, 7, 7, 14, 7, 7, 7, 7, 15, 16, 7, 17, 18, 19, 20, + 21, 7, 22, 23, 7, 7, 24, 25, 26, 27, 28, 7, 7, 29, 30, 31, + 32, 33, 34, 35, 36, 7, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 54, 55, 52, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, + 78, 79, 80, 78, 78, 81, 82, 78, 83, 84, 85, 86, 87, 88, 89, 78, + 78, 90, 91, 92, 93, 7, 94, 95, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 96, 7, 97, 98, 99, 7, 100, 7, 101, 78, 102, 7, 7, 103, + 104, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 105, 106, 7, 7, 107, 108, 109, 110, 111, 78, 112, 113, 114, + 115, 7, 7, 116, 117, 118, 7, 119, 120, 121, 61, 78, 78, 78, 122, 78, + 123, 78, 124, 125, 126, 127, 128, 78, 129, 130, 131, 132, 133, 134, 7, 135, + 7, 136, 137, 138, 35, 139, 140, 141, 7, 7, 7, 7, 7, 7, 9, 9, + 7, 7, 7, 7, 7, 7, 7, 7, 103, 7, 142, 138, 7, 143, 144, 145, + 146, 147, 148, 149, 150, 78, 127, 151, 152, 153, 154, 7, 155, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 156, 7, 157, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 7, 7, 7, 7, 7, 7, 7, 158, 7, 94, 7, 159, 160, 161, 161, 9, + 78, 162, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 163, 164, 78, 78, 165, 166, 166, 167, 168, 15, 7, 7, 169, 7, 78, 170, + 78, 78, 78, 78, 78, 78, 170, 171, 166, 166, 172, 78, 78, 78, 78, 78, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 173, 78, 174, 138, 7, 7, 7, 7, 7, 7, 7, 7, + 175, 176, 7, 177, 178, 7, 7, 179, 180, 7, 7, 7, 7, 7, 181, 182, + 183, 184, 7, 185, 186, 130, 187, 188, 30, 189, 190, 191, 39, 192, 193, 194, + 7, 195, 196, 197, 78, 198, 199, 200, 201, 202, 7, 203, 7, 7, 7, 204, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 205, 206, 207, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 208, 209, 210, 7, 7, 211, 212, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 138, 174, 7, 213, 7, 214, 215, + 216, 217, 218, 219, 7, 7, 7, 220, 221, 2, 3, 222, 223, 120, 224, 225, + 226, 227, 228, 78, 7, 7, 7, 229, 78, 78, 7, 230, 78, 78, 78, 231, + 78, 78, 78, 78, 191, 7, 232, 233, 7, 234, 35, 235, 138, 7, 236, 78, + 7, 7, 7, 7, 138, 237, 238, 207, 7, 239, 7, 240, 241, 242, 7, 185, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 160, 119, 214, 243, 244, 78, 78, + 245, 246, 119, 160, 120, 78, 78, 247, 119, 248, 78, 78, 7, 8, 78, 78, + 249, 250, 78, 191, 191, 78, 85, 251, 7, 119, 119, 252, 211, 78, 78, 78, + 7, 7, 155, 78, 7, 252, 7, 252, 7, 253, 30, 254, 255, 78, 78, 78, + 78, 78, 78, 78, 7, 256, 257, 258, 191, 259, 260, 174, 261, 174, 262, 160, + 133, 263, 264, 265, 133, 266, 267, 268, 133, 269, 270, 271, 133, 192, 272, 78, + 273, 274, 275, 78, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, + 7, 288, 289, 290, 7, 27, 291, 78, 78, 78, 78, 78, 7, 292, 293, 78, + 7, 27, 294, 78, 7, 295, 296, 297, 298, 299, 78, 78, 78, 78, 78, 78, + 7, 300, 78, 78, 78, 7, 7, 301, 302, 303, 304, 78, 78, 305, 306, 307, + 308, 309, 310, 7, 311, 174, 7, 116, 78, 78, 78, 78, 78, 78, 7, 312, + 313, 314, 312, 182, 315, 316, 78, 78, 317, 318, 319, 320, 321, 114, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 322, 323, 324, 325, 78, 78, 326, 78, 78, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 248, 78, 78, 78, + 7, 7, 7, 169, 7, 7, 7, 7, 7, 7, 327, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 174, 7, 7, 232, + 7, 328, 329, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 229, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 330, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 178, 331, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 116, 120, 237, 7, 120, 237, 332, 7, 333, 334, 335, 102, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 7, 336, 78, 78, 78, 78, + 78, 78, 7, 7, 78, 78, 78, 78, 7, 7, 337, 9, 338, 78, 78, 339, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 340, + 341, 78, 78, 78, 78, 78, 78, 78, 78, 342, 343, 344, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 7, 7, 7, 345, 346, 347, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 348, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 9, 349, 264, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 350, 351, 352, 78, 78, + 78, 78, 353, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 7, 7, 354, 7, 355, 356, 357, 7, 358, 359, 360, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 361, 362, 95, 354, 354, 363, 363, 313, 313, 364, 365, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 9, 366, 9, 367, 368, 369, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 120, 370, 78, 78, 78, 78, 78, 78, + 371, 372, 7, 373, 374, 78, 78, 78, 7, 375, 376, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 174, 377, 7, 378, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 174, 378, 78, 78, 78, 78, 78, 78, 174, 379, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 380, + 7, 7, 7, 7, 7, 7, 381, 78, 7, 7, 382, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 357, 383, 384, 385, 386, 387, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 174, 203, 203, 157, 78, 78, 388, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 389, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 348, + 390, 9, 9, 9, 78, 78, 78, 78, 9, 9, 9, 9, 9, 9, 9, 391, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78 +}; + +static RE_UINT8 re_word_break_table_3[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 5, 0, 0, 0, 0, 6, 0, 0, 0, 0, 7, 0, 8, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 7, 0, 0, 0, 0, + 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 12, + 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 13, 0, 0, + 0, 0, 0, 0, 0, 11, 0, 10, 0, 0, 11, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 0, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, 0, 11, 11, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 11, 11, 11, 11, 11, 0, 11, 11, 0, 0, 11, 11, 11, 11, 7, 11, + 0, 0, 0, 0, 0, 0, 11, 10, 11, 11, 11, 0, 11, 0, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 0, 14, 14, 14, 14, 14, 14, 14, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 0, 0, 11, 11, 11, 11, 0, 11, 10, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 7, 11, 0, 0, 0, 0, 0, + 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 14, + 0, 14, 14, 0, 14, 14, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 15, + 15, 15, 15, 11, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 7, 7, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 13, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 7, 0, 11, 11, + 14, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 0, 11, 14, 14, 14, 14, 14, 14, 14, 9, 0, 14, + 14, 14, 14, 14, 14, 11, 11, 14, 14, 0, 14, 14, 14, 14, 11, 11, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 0, 0, 11, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, + 11, 14, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 11, 11, 0, 0, 7, 0, 11, 0, 0, 14, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 14, 14, 14, 14, 11, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 11, 14, 14, 14, 11, 14, 14, 14, 14, 14, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 14, 14, 14, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 0, 11, 11, 11, 11, 11, 11, 0, + 9, 9, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 9, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 14, 14, 14, 11, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 11, 14, 14, 14, 14, 14, 14, 14, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 14, 14, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 14, 14, 14, 0, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 11, + 11, 0, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 11, 11, 11, 11, 11, 11, + 11, 0, 11, 0, 0, 0, 11, 11, 11, 11, 0, 0, 14, 11, 14, 14, + 14, 14, 14, 14, 14, 0, 0, 14, 14, 0, 0, 14, 14, 14, 11, 0, + 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 11, 11, 0, 11, + 11, 11, 14, 14, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 14, 0, + 0, 14, 14, 14, 0, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 11, + 11, 0, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 11, 11, 11, 11, 11, 11, + 11, 0, 11, 11, 0, 11, 11, 0, 11, 11, 0, 0, 14, 0, 14, 14, + 14, 14, 14, 0, 0, 0, 0, 14, 14, 0, 0, 14, 14, 14, 0, 0, + 0, 14, 0, 0, 0, 0, 0, 0, 0, 11, 11, 11, 11, 0, 11, 0, + 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 14, 14, 11, 11, 11, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 14, 14, 14, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 11, + 11, 11, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 11, 11, 11, 11, 11, 11, + 11, 0, 11, 11, 0, 11, 11, 11, 11, 11, 0, 0, 14, 11, 14, 14, + 14, 14, 14, 14, 14, 14, 0, 14, 14, 14, 0, 14, 14, 14, 0, 0, + 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 14, 14, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 14, 14, 14, 14, 14, 14, + 0, 14, 14, 14, 0, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 11, + 11, 0, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 14, 14, 14, 14, 14, 0, 0, 14, 14, 0, 0, 14, 14, 14, 0, 0, + 0, 0, 0, 0, 0, 14, 14, 14, 0, 0, 0, 0, 11, 11, 0, 11, + 11, 11, 14, 14, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 14, 11, 0, 11, 11, 11, 11, 11, 11, 0, 0, 0, 11, 11, + 11, 0, 11, 11, 11, 11, 0, 0, 0, 11, 11, 0, 11, 0, 11, 11, + 0, 0, 0, 11, 11, 0, 0, 0, 11, 11, 11, 0, 0, 0, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 14, 14, + 14, 14, 14, 0, 0, 0, 14, 14, 14, 0, 14, 14, 14, 14, 0, 0, + 11, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 11, 11, 11, 11, 11, 11, 11, 11, 0, 11, 11, + 11, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 14, 11, 14, 14, + 14, 14, 14, 14, 14, 0, 14, 14, 14, 0, 14, 14, 14, 14, 0, 0, + 0, 0, 0, 0, 0, 14, 14, 0, 11, 11, 11, 0, 0, 11, 0, 0, + 11, 11, 14, 14, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 14, 14, 14, 0, 11, 11, 11, 11, 11, 11, 11, 11, 0, 11, 11, + 11, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 0, 11, 11, 11, 11, 11, 0, 0, 14, 11, 14, 14, + 14, 14, 14, 14, 14, 0, 14, 14, 14, 0, 14, 14, 14, 14, 0, 0, + 0, 0, 0, 0, 0, 14, 14, 0, 0, 0, 0, 0, 0, 11, 11, 0, + 11, 11, 14, 14, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 11, 11, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 11, 11, + 11, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 14, 14, 11, 14, 14, + 14, 14, 14, 14, 14, 0, 14, 14, 14, 0, 14, 14, 14, 14, 11, 0, + 0, 0, 0, 0, 11, 11, 11, 14, 0, 0, 0, 0, 0, 0, 0, 11, + 11, 11, 14, 14, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 11, 11, 11, 11, 11, + 0, 14, 14, 14, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 11, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 14, 0, 0, 0, 0, 14, + 14, 14, 14, 14, 14, 0, 14, 0, 14, 14, 14, 14, 14, 14, 14, 14, + 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 0, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 14, 0, 0, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 14, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 14, 0, 14, 0, 14, 0, 0, 0, 0, 14, 14, + 11, 11, 11, 11, 11, 11, 11, 11, 0, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, + 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 0, 14, 14, 11, 11, 11, 11, 11, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 0, 0, 0, 0, 14, 14, + 14, 0, 14, 14, 14, 0, 0, 14, 14, 14, 14, 14, 14, 14, 0, 0, + 0, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 14, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 14, 14, 14, 14, 0, 0, + 11, 11, 11, 11, 11, 11, 0, 11, 0, 0, 0, 0, 0, 11, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 11, 11, 11, 11, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 0, 11, 0, 11, 11, 11, 11, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 11, 11, 11, 11, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 0, 11, 11, 11, 11, 0, 0, 11, 11, 11, 11, 11, 11, 11, 0, + 11, 0, 11, 11, 11, 11, 0, 0, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 0, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 0, 11, 11, 11, 11, 0, 0, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 14, 14, 14, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 0, 0, 11, 11, 11, 11, 11, 11, 0, 0, + 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 4, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 11, 11, + 11, 0, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 13, 14, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 14, 14, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 14, 11, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 14, 14, 14, 14, 14, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 14, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 11, 11, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 11, 11, 11, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 11, 11, 11, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 11, 11, 11, 11, 14, 11, 11, + 11, 11, 11, 11, 14, 11, 11, 14, 14, 14, 11, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 0, 0, 11, 11, 11, 11, 11, 11, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 0, 11, 0, 11, 0, 11, 0, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 0, 11, 11, 11, 11, 11, 11, 11, 0, 11, 0, + 0, 0, 11, 11, 11, 0, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, + 11, 11, 11, 11, 0, 0, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, + 0, 0, 11, 11, 11, 0, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 0, 14, 16, 13, 13, + 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 8, 0, 0, 10, 2, 2, 13, 13, 13, 13, 13, 12, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, + 12, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, + 13, 13, 13, 13, 13, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 11, 0, 0, 0, 0, 11, 0, 0, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 0, 11, 0, 0, 0, 11, 11, 11, 11, 11, 0, 0, + 0, 0, 0, 0, 11, 0, 11, 0, 11, 0, 11, 11, 11, 11, 0, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 11, 11, 11, 11, + 0, 0, 0, 0, 0, 11, 11, 11, 11, 11, 0, 0, 0, 0, 11, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, 0, 11, 11, 11, 11, 14, + 14, 14, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, 11, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 0, 11, 11, 11, 11, 11, 11, 11, 0, + 11, 11, 11, 11, 11, 11, 11, 0, 11, 11, 11, 11, 11, 11, 11, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, + 0, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 11, 11, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 17, 17, 0, 0, 0, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 17, 17, 17, 17, + 0, 0, 0, 0, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 11, 11, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 14, + 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 14, 14, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, + 11, 11, 0, 11, 0, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 14, 11, 11, 11, 14, 11, 11, 11, 11, 14, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 14, 14, 14, 14, 14, 0, 0, 0, 0, 14, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 11, 11, 11, 11, 11, 11, 0, 0, 0, 11, 0, 11, 11, 14, + 11, 11, 11, 11, 11, 11, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 14, 11, 11, 11, 11, 11, 11, 11, 11, 14, 14, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 0, 14, 14, 14, 0, 0, 14, 14, 0, 0, 0, 0, 0, 14, 14, + 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 14, 14, 14, 14, 14, + 0, 0, 11, 11, 11, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 11, 11, 11, 11, 11, 11, 0, 0, 11, 11, 11, 11, 11, 11, 0, + 0, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 0, 11, 11, 11, 11, 11, 11, 11, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 14, 14, 14, 14, 14, 14, 14, 14, 0, 14, 14, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, 15, 14, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 0, 15, 0, + 15, 15, 0, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 0, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 0, 0, 0, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 12, + 7, 0, 8, 0, 7, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 13, + 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 7, 0, 8, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 7, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 14, 14, + 0, 0, 11, 11, 11, 11, 11, 11, 0, 0, 11, 11, 11, 11, 11, 11, + 0, 0, 11, 11, 11, 11, 11, 11, 0, 0, 11, 11, 11, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 0, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 11, 11, 0, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 0, 0, 0, 0, 11, 11, 11, 11, 11, 11, 11, 11, + 0, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 0, 0, 0, 0, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 11, 11, 11, 11, + 11, 11, 11, 0, 11, 11, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 0, 11, 11, 11, 11, 11, 11, 11, 0, 11, 11, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 0, 0, 11, 0, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 0, 11, 11, 0, 0, 0, 11, 0, 0, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 0, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, 0, + 11, 14, 14, 14, 0, 14, 14, 0, 0, 0, 0, 0, 14, 14, 14, 14, + 11, 11, 11, 11, 0, 11, 11, 11, 0, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 0, 0, 14, 14, 14, 0, 0, 0, 0, 14, + 11, 11, 11, 11, 11, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 0, 0, 0, 14, 14, 14, 14, 14, 0, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 14, 14, 0, 0, 0, + 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, + 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 14, 11, 11, 14, 14, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 9, 0, 0, + 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 0, 0, 0, 11, 14, 14, 11, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 14, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 11, 11, 11, 11, 0, 0, 0, 0, 14, 14, 14, 14, 0, 14, 14, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 11, 0, 11, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 14, 11, + 11, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 0, 11, 0, 11, 11, 11, 11, 0, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 0, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 11, + 11, 0, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 11, 11, 11, 11, 11, 11, + 11, 0, 11, 11, 0, 11, 11, 11, 11, 11, 0, 14, 14, 11, 14, 14, + 14, 14, 14, 14, 14, 0, 0, 14, 14, 0, 0, 14, 14, 14, 0, 0, + 11, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 11, 11, 11, + 11, 11, 14, 14, 0, 0, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, + 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 11, 0, 0, 11, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 0, 11, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 0, 14, 0, 0, 14, 0, 14, 14, 14, 14, 0, 14, 14, 14, 14, + 14, 11, 14, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 11, 11, 11, 11, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 14, 11, + 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 11, 11, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 14, + 14, 14, 14, 14, 14, 14, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 11, 11, 11, 11, 14, 14, 0, 0, + 14, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 11, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, + 11, 11, 11, 11, 11, 11, 11, 0, 0, 11, 0, 0, 11, 11, 11, 11, + 11, 11, 11, 11, 0, 11, 11, 0, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 14, 14, 14, 14, 14, 14, 0, 14, 14, 0, 0, 14, 14, 14, 14, 11, + 14, 11, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 14, 14, 14, 14, 14, 14, 14, 0, 0, 14, 14, 14, 14, 14, 14, + 14, 11, 0, 11, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 14, 14, 14, 14, 14, 14, 14, 11, 14, 14, 14, 14, 0, + 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 11, 0, 0, + 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 14, + 14, 14, 14, 14, 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, 14, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 0, 11, 11, 0, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 14, 14, 14, 14, 14, 14, 0, 0, 0, 14, 0, 14, 14, 0, 14, + 14, 14, 14, 14, 14, 14, 11, 14, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 0, 11, 11, 0, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 14, 14, 14, 14, 14, 0, + 14, 14, 0, 14, 14, 14, 14, 14, 11, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 11, 14, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 14, 14, + 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 14, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 14, 11, 11, 11, 11, 11, 11, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, + 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 14, + 11, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 14, + 14, 14, 14, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 0, 11, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 17, 17, 17, 17, 0, 17, 17, 17, 17, 17, 17, 17, 0, 17, 17, 0, + 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 14, 14, 0, + 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 0, 0, 0, 14, 14, 14, + 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, + 14, 14, 14, 0, 0, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 11, 11, + 0, 0, 11, 0, 0, 11, 11, 0, 0, 11, 11, 11, 11, 0, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 11, 0, 11, 11, 11, + 11, 11, 11, 11, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 0, 11, 11, 11, 11, 0, 0, 11, 11, 11, + 11, 11, 11, 11, 11, 0, 11, 11, 11, 11, 11, 11, 11, 0, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 11, 11, 11, 11, 0, + 11, 11, 11, 11, 11, 0, 11, 0, 0, 0, 11, 11, 11, 11, 11, 11, + 11, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 0, 0, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 0, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, + 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, + 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 14, 14, 14, 14, 14, + 14, 14, 0, 14, 14, 0, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 11, 11, 11, 11, 11, 11, 11, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 11, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 14, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 14, 14, 14, 14, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 14, 14, + 11, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 0, 11, 11, 11, 11, 0, 11, 11, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, + 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 14, 14, 14, 14, 14, 14, 14, 11, 0, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, + 0, 11, 11, 0, 11, 0, 0, 11, 0, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 0, 11, 11, 11, 11, 0, 11, 0, 11, 0, 0, 0, 0, + 0, 0, 11, 0, 0, 0, 0, 11, 0, 11, 0, 11, 0, 11, 11, 11, + 0, 11, 11, 0, 11, 0, 0, 11, 0, 11, 0, 11, 0, 11, 0, 11, + 0, 11, 11, 0, 11, 0, 0, 11, 11, 11, 11, 0, 11, 11, 11, 11, + 11, 11, 11, 0, 11, 11, 11, 11, 0, 11, 11, 11, 11, 0, 11, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, + 0, 11, 11, 11, 0, 11, 11, 11, 11, 11, 0, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, + 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +RE_UINT32 re_get_word_break(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = codepoint & 0x1F; + + v = re_word_break_table_1[field_2]; + v = re_word_break_table_2[(v << 5) | field_1]; + v = re_word_break_table_3[(v << 5) | field_0]; + + return v; +} + +/* XDigit. */ +static RE_UINT8 re_xdigit_table_1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 10, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 11, + 8, 12, 8, 13, 14, 15, 16, 17, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 18, 8, 19, 20, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 21, 8, 22, 8, 8, 23, 24, 25, 8, 8, 8, 26, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 +}; + +static RE_UINT8 re_xdigit_table_2[] = { + 0, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, + 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, + 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, + 0, 0, 1, 0, 0, 0, 1, 0, 0, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 0, 1, 1, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 4, 0, 0, 0, 1, 0, 6, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 7, 8, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 3, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 10, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 11, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 +}; + +static RE_UINT8 re_xdigit_table_3[] = { + 0, 0, 0, 0, 0, 0, 255, 3, 126, 0, 0, 0, 255, 3, 0, 0, + 192, 255, 0, 0, 255, 3, 255, 3, 0, 0, 192, 255, 255, 3, 255, 255, + 15, 0, 0, 0, 0, 192, 255, 255, 255, 255, 255, 255, 0, 0, 254, 7 +}; + +RE_UINT32 re_get_xdigit(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_xdigit_table_1[field_2]; + v = re_xdigit_table_2[(v << 5) | field_1]; + v = re_xdigit_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* XID_Continue. */ +static RE_UINT8 re_xid_continue_table_1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 11, 12, 12, 12, + 12, 12, 12, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 14, 15, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 16, 9, 9, 9, 9, 9, 9, 9, 9, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 9, 29, 12, 30, 12, 12, + 31, 32, 9, 9, 9, 9, 9, 9, 33, 9, 34, 35, 12, 12, 12, 12, + 12, 36, 12, 37, 9, 9, 9, 9, 9, 9, 9, 38, 39, 9, 9, 40, + 9, 9, 9, 41, 42, 43, 44, 45, 46, 47, 48, 49, 9, 9, 50, 9, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 51, 12, 12, 12, 52, 53, 12, + 12, 12, 12, 54, 12, 12, 12, 12, 12, 12, 55, 56, 9, 9, 57, 9, + 12, 12, 12, 12, 58, 12, 12, 12, 59, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 60, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 +}; + +static RE_UINT16 re_xid_continue_table_2[] = { + 0, 1, 2, 3, 0, 4, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 7, 8, 6, 6, 6, 9, 10, 11, 6, 12, + 6, 6, 6, 6, 13, 6, 6, 6, 6, 14, 15, 6, 16, 17, 18, 19, + 20, 6, 6, 21, 6, 6, 22, 23, 24, 6, 25, 6, 6, 26, 6, 27, + 6, 28, 29, 30, 31, 6, 6, 11, 6, 6, 6, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 42, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 52, 6, 60, 61, 62, 63, 64, 65, + 66, 67, 68, 0, 69, 70, 71, 0, 72, 73, 74, 75, 76, 77, 78, 0, + 6, 6, 79, 6, 80, 6, 81, 82, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 83, 6, 84, 85, 86, 6, 87, 6, 88, 89, 90, 6, 6, 91, + 66, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 92, 3, 6, 6, 93, 94, 95, 96, 97, 6, 6, 98, 99, + 100, 6, 6, 101, 6, 30, 6, 102, 103, 104, 105, 106, 6, 107, 108, 0, + 29, 6, 103, 109, 110, 111, 112, 0, 6, 6, 113, 114, 6, 6, 6, 96, + 6, 115, 116, 80, 30, 88, 117, 67, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 91, 6, 118, 80, 6, 119, 120, 121, + 122, 123, 124, 125, 126, 0, 126, 127, 128, 129, 130, 6, 131, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 6, 6, 6, 6, 6, 6, 132, 6, 81, 6, 133, 134, 135, 135, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 136, 137, 66, 6, 138, 66, 6, 6, 139, 14, 6, 6, 112, 6, 0, 24, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 0, 0, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 140, 0, 24, 80, 6, 6, 6, 6, 6, 6, 6, 6, + 141, 142, 6, 143, 6, 6, 6, 26, 144, 145, 6, 6, 146, 6, 147, 148, + 6, 149, 6, 96, 6, 6, 150, 151, 6, 152, 96, 77, 6, 6, 153, 103, + 6, 134, 154, 155, 6, 6, 156, 157, 158, 159, 82, 79, 6, 6, 6, 160, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 161, 162, 29, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 152, 6, 6, 163, 0, 164, 165, 166, 6, 6, 26, 167, 6, + 6, 6, 80, 168, 6, 6, 6, 6, 6, 80, 24, 6, 169, 6, 170, 1, + 90, 171, 172, 173, 6, 6, 6, 77, 1, 2, 3, 139, 6, 103, 174, 0, + 175, 176, 177, 0, 6, 6, 6, 67, 0, 0, 6, 95, 0, 0, 0, 178, + 0, 0, 0, 0, 77, 6, 179, 180, 6, 181, 30, 67, 80, 6, 182, 0, + 6, 6, 6, 6, 80, 79, 183, 29, 6, 184, 6, 185, 186, 187, 6, 96, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 134, 102, 170, 188, 189, 0, 0, + 190, 191, 102, 134, 103, 0, 0, 192, 102, 163, 0, 0, 6, 193, 0, 0, + 194, 195, 0, 77, 77, 0, 74, 196, 6, 102, 102, 197, 26, 0, 0, 0, + 6, 6, 131, 0, 6, 197, 6, 197, 6, 198, 6, 199, 200, 0, 0, 0, + 0, 0, 0, 0, 6, 201, 202, 203, 77, 204, 179, 24, 200, 24, 205, 134, + 6, 6, 196, 206, 6, 67, 207, 208, 6, 209, 210, 211, 6, 6, 212, 0, + 213, 193, 214, 0, 215, 216, 6, 217, 33, 218, 219, 220, 221, 12, 222, 223, + 6, 6, 224, 214, 6, 6, 225, 0, 0, 0, 0, 0, 6, 226, 227, 0, + 6, 6, 228, 0, 6, 101, 79, 229, 88, 230, 196, 0, 0, 0, 0, 0, + 6, 67, 0, 0, 0, 6, 6, 231, 232, 233, 234, 0, 0, 235, 236, 237, + 6, 103, 204, 6, 238, 24, 6, 101, 0, 0, 0, 0, 0, 0, 6, 239, + 240, 5, 239, 148, 169, 241, 0, 0, 242, 243, 198, 244, 245, 99, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 134, 246, 247, 248, 0, 0, 249, 0, 0, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 163, 0, 0, 0, + 6, 6, 6, 112, 6, 6, 6, 6, 6, 6, 229, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 6, 6, 179, + 6, 90, 102, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 67, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 163, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 101, 103, 79, 6, 103, 79, 106, 6, 134, 234, 250, 90, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 113, 0, 0, 0, 0, + 0, 0, 6, 6, 0, 0, 0, 0, 6, 6, 251, 6, 252, 0, 0, 253, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 115, + 6, 6, 6, 6, 6, 6, 102, 123, 131, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 255, 256, 210, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 29, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 6, 6, 257, 258, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 152, 196, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 259, 260, 261, 0, 0, + 0, 0, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 6, 209, 6, 262, 263, 264, 6, 265, 266, 267, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 268, 269, 82, 209, 209, 270, 270, 240, 240, 271, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 272, 6, 273, 274, 275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 103, 276, 0, 0, 0, 0, 0, 0, + 277, 278, 6, 28, 279, 0, 0, 0, 6, 280, 281, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 24, 112, 6, 163, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 24, 163, 0, 0, 0, 0, 0, 0, 24, 67, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 282, + 6, 6, 6, 6, 6, 6, 283, 0, 6, 6, 230, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 264, 284, 285, 286, 287, 288, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 0, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 163, 6, 6, 6, 6, 6, 6, + 80, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 289, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 290, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 30, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 90, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, 90, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_xid_continue_table_3[] = { + 0, 0, 0, 0, 0, 0, 255, 3, 254, 255, 255, 135, 254, 255, 255, 7, + 0, 4, 160, 4, 255, 255, 127, 255, 255, 255, 255, 255, 195, 255, 3, 0, + 31, 80, 0, 0, 255, 255, 223, 184, 192, 215, 255, 255, 251, 255, 255, 255, + 255, 255, 191, 255, 251, 252, 255, 255, 255, 255, 254, 255, 255, 255, 127, 2, + 255, 1, 254, 255, 255, 255, 255, 191, 182, 0, 255, 255, 255, 135, 7, 0, + 0, 0, 255, 7, 255, 195, 255, 255, 255, 255, 239, 159, 255, 253, 255, 159, + 0, 0, 255, 255, 255, 231, 255, 255, 255, 255, 3, 0, 255, 255, 63, 36, + 255, 63, 0, 0, 255, 255, 255, 15, 255, 7, 255, 255, 255, 126, 128, 255, + 207, 255, 254, 255, 239, 159, 249, 255, 255, 253, 197, 243, 159, 121, 128, 176, + 207, 255, 3, 80, 238, 135, 249, 255, 255, 253, 109, 211, 135, 57, 2, 94, + 192, 255, 63, 0, 238, 191, 251, 255, 255, 253, 237, 243, 191, 59, 1, 0, + 207, 255, 0, 254, 238, 159, 249, 255, 159, 57, 224, 176, 207, 255, 2, 0, + 236, 199, 61, 214, 24, 199, 255, 195, 199, 61, 129, 0, 192, 255, 0, 0, + 255, 223, 253, 255, 255, 253, 255, 243, 223, 61, 96, 39, 207, 255, 0, 0, + 239, 223, 253, 255, 255, 253, 239, 243, 223, 61, 96, 96, 207, 255, 14, 0, + 223, 125, 240, 128, 207, 255, 0, 252, 238, 255, 127, 252, 255, 255, 251, 47, + 127, 132, 95, 255, 192, 255, 12, 0, 254, 255, 255, 255, 255, 255, 255, 7, + 255, 127, 255, 3, 214, 247, 255, 255, 175, 255, 255, 63, 95, 127, 255, 243, + 1, 0, 0, 3, 255, 3, 160, 194, 255, 254, 255, 255, 255, 31, 254, 255, + 223, 255, 255, 254, 255, 255, 255, 31, 64, 0, 0, 0, 255, 3, 255, 255, + 255, 255, 255, 63, 191, 32, 255, 255, 255, 255, 255, 247, 255, 61, 127, 61, + 255, 61, 255, 255, 255, 255, 61, 127, 61, 255, 127, 255, 255, 255, 61, 255, + 255, 255, 255, 231, 0, 254, 3, 0, 255, 255, 0, 0, 255, 255, 63, 63, + 255, 159, 255, 255, 255, 199, 255, 1, 255, 255, 63, 128, 255, 255, 31, 0, + 255, 255, 15, 0, 255, 223, 13, 0, 255, 255, 143, 48, 255, 3, 0, 0, + 0, 184, 255, 3, 255, 255, 255, 1, 255, 255, 63, 0, 255, 255, 255, 127, + 255, 15, 255, 15, 192, 255, 255, 255, 255, 63, 31, 0, 255, 15, 255, 255, + 255, 3, 255, 7, 255, 255, 255, 159, 255, 3, 255, 3, 128, 0, 255, 191, + 255, 127, 0, 0, 255, 31, 255, 3, 0, 248, 15, 0, 255, 255, 255, 0, + 255, 227, 255, 255, 0, 0, 247, 255, 63, 63, 255, 170, 255, 255, 223, 95, + 220, 31, 207, 15, 255, 31, 220, 31, 0, 48, 0, 0, 0, 0, 0, 128, + 1, 0, 16, 0, 0, 0, 2, 128, 0, 0, 255, 31, 226, 255, 1, 0, + 132, 252, 47, 63, 80, 253, 255, 243, 224, 67, 0, 0, 255, 1, 0, 0, + 31, 248, 15, 0, 255, 128, 0, 128, 255, 255, 127, 0, 127, 127, 127, 127, + 224, 0, 0, 0, 254, 255, 62, 31, 255, 255, 127, 230, 224, 255, 255, 255, + 255, 31, 0, 0, 255, 31, 255, 255, 255, 15, 0, 0, 255, 255, 240, 191, + 0, 0, 128, 255, 252, 255, 255, 255, 255, 249, 255, 255, 255, 63, 235, 31, + 0, 0, 252, 255, 255, 16, 0, 0, 63, 0, 255, 3, 255, 255, 255, 232, + 255, 63, 255, 255, 1, 128, 255, 3, 255, 63, 255, 3, 255, 255, 127, 252, + 7, 0, 0, 56, 255, 255, 124, 0, 126, 126, 126, 0, 127, 127, 255, 255, + 255, 55, 255, 3, 15, 0, 255, 255, 127, 248, 255, 255, 255, 255, 255, 3, + 127, 0, 248, 224, 255, 253, 127, 95, 219, 255, 255, 255, 0, 0, 248, 255, + 240, 255, 255, 255, 255, 255, 252, 255, 255, 0, 0, 0, 255, 255, 24, 0, + 0, 224, 0, 0, 0, 0, 138, 170, 252, 252, 252, 28, 255, 239, 255, 255, + 127, 255, 255, 183, 255, 63, 255, 63, 0, 0, 0, 32, 255, 255, 1, 0, + 1, 0, 0, 0, 0, 224, 255, 255, 15, 255, 62, 0, 255, 255, 15, 255, + 255, 0, 255, 255, 15, 0, 255, 247, 255, 247, 183, 255, 251, 255, 251, 27, + 191, 255, 255, 255, 255, 255, 253, 7, 63, 253, 255, 255, 255, 255, 191, 145, + 255, 255, 55, 0, 255, 255, 255, 192, 111, 240, 239, 254, 255, 255, 63, 135, + 127, 0, 0, 0, 255, 255, 7, 0, 255, 0, 255, 3, 63, 190, 255, 255, + 63, 0, 0, 0, 255, 27, 3, 0, 28, 0, 0, 0, 0, 0, 0, 240, + 128, 0, 255, 255, 31, 0, 0, 0, 192, 255, 63, 128, 4, 0, 255, 255, + 255, 1, 255, 3, 255, 255, 223, 255, 240, 0, 255, 255, 255, 255, 79, 0, + 31, 222, 255, 23, 255, 255, 251, 255, 3, 0, 0, 0, 127, 189, 255, 191, + 255, 1, 255, 255, 255, 7, 255, 3, 255, 253, 237, 251, 159, 57, 129, 224, + 207, 31, 31, 0, 255, 75, 255, 255, 165, 247, 15, 0, 6, 0, 0, 0, + 255, 7, 255, 195, 191, 0, 255, 3, 255, 255, 63, 255, 1, 0, 0, 63, + 17, 0, 255, 3, 15, 0, 0, 0, 255, 15, 255, 3, 255, 3, 0, 128, + 127, 242, 111, 255, 255, 255, 191, 249, 15, 0, 255, 3, 255, 252, 255, 255, + 255, 255, 255, 252, 27, 0, 0, 0, 255, 255, 255, 35, 1, 0, 255, 3, + 255, 253, 255, 255, 255, 254, 127, 0, 127, 251, 255, 255, 255, 255, 127, 180, + 191, 253, 255, 255, 255, 127, 251, 1, 255, 255, 253, 255, 255, 255, 255, 199, + 7, 0, 255, 7, 0, 0, 1, 0, 248, 255, 255, 224, 255, 135, 255, 255, + 255, 128, 255, 255, 27, 0, 3, 0, 0, 0, 239, 111, 7, 0, 4, 0, + 0, 0, 39, 0, 255, 7, 255, 31, 255, 1, 255, 99, 224, 227, 7, 248, + 231, 15, 0, 0, 0, 60, 0, 0, 255, 255, 255, 223, 100, 222, 255, 235, + 239, 255, 255, 255, 191, 231, 223, 223, 255, 255, 255, 123, 95, 252, 253, 255, + 63, 255, 255, 255, 253, 255, 255, 247, 255, 127, 255, 255, 247, 207, 255, 255, + 255, 255, 127, 248, 255, 31, 32, 0, 16, 0, 0, 248, 254, 255, 0, 0, + 224, 7, 0, 0, 127, 255, 255, 249, 219, 7, 255, 255, 0, 128, 0, 0, + 255, 31, 255, 63, 255, 67, 0, 0, 127, 111, 255, 127, 31, 0, 127, 0, + 150, 254, 247, 10, 132, 234, 150, 170, 150, 247, 247, 94, 255, 251, 255, 15, + 238, 251, 255, 15, 3, 0, 255, 255, 1, 0, 255, 255 +}; + +RE_UINT32 re_get_xid_continue(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_xid_continue_table_1[field_2]; + v = re_xid_continue_table_2[(v << 5) | field_1]; + v = re_xid_continue_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* XID_Start. */ +static RE_UINT8 re_xid_start_table_1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 11, 12, 12, 12, + 12, 12, 12, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 14, 15, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 16, 9, 9, 9, 9, 9, 9, 9, 9, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 9, 29, 12, 30, 12, 12, + 31, 32, 9, 9, 9, 9, 9, 9, 33, 9, 34, 35, 12, 12, 12, 12, + 12, 36, 12, 37, 9, 9, 9, 9, 9, 9, 9, 38, 39, 9, 9, 40, + 9, 9, 9, 9, 9, 41, 9, 42, 43, 44, 45, 46, 9, 9, 9, 9, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 47, 12, 12, 12, 48, 49, 12, + 12, 12, 12, 50, 12, 12, 12, 12, 12, 12, 51, 52, 9, 9, 53, 9, + 12, 12, 12, 12, 54, 12, 12, 12, 55, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 +}; + +static RE_UINT16 re_xid_start_table_2[] = { + 0, 0, 1, 1, 0, 2, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 5, 6, 0, 0, 0, 7, 8, 9, 4, 10, + 4, 4, 4, 4, 11, 4, 4, 4, 4, 12, 13, 4, 14, 0, 15, 16, + 0, 4, 17, 18, 4, 4, 19, 20, 21, 22, 23, 4, 4, 24, 25, 26, + 27, 28, 29, 30, 31, 4, 32, 0, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 46, 50, 51, 52, 53, 47, 0, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 0, + 69, 70, 68, 0, 71, 72, 73, 0, 74, 0, 75, 76, 77, 0, 0, 0, + 4, 78, 79, 80, 81, 4, 82, 83, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 84, 4, 85, 86, 87, 4, 88, 4, 89, 0, 22, 4, 4, 90, + 69, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 91, 1, 4, 4, 92, 93, 94, 94, 95, 4, 96, 97, 0, + 0, 4, 4, 29, 4, 98, 4, 99, 100, 0, 15, 101, 4, 102, 32, 0, + 103, 4, 104, 0, 0, 105, 0, 0, 106, 96, 107, 0, 108, 109, 4, 110, + 4, 111, 112, 113, 30, 114, 0, 115, 4, 4, 4, 4, 4, 4, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 90, 4, 116, 113, 4, 117, 118, 119, + 0, 0, 0, 120, 121, 0, 0, 0, 122, 123, 124, 4, 14, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 125, 4, 82, 4, 126, 103, 127, 127, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 128, 129, 69, 4, 130, 69, 4, 83, 106, 12, 4, 4, 131, 4, 0, 15, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 76, 0, 15, 113, 4, 4, 4, 4, 4, 4, 4, 4, + 132, 133, 4, 134, 113, 4, 4, 22, 135, 136, 4, 4, 137, 4, 138, 139, + 140, 141, 4, 96, 136, 96, 0, 142, 25, 143, 68, 144, 33, 145, 146, 147, + 4, 14, 148, 149, 4, 150, 151, 152, 153, 154, 83, 155, 4, 4, 4, 141, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 156, 157, 158, + 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 159, 4, 4, 160, 0, 161, 162, 163, 4, 4, 94, 164, 4, + 4, 4, 113, 33, 4, 4, 4, 4, 4, 113, 15, 4, 165, 4, 166, 167, + 0, 0, 0, 168, 4, 4, 4, 144, 0, 1, 1, 169, 113, 100, 170, 0, + 171, 172, 173, 0, 4, 4, 4, 89, 0, 0, 4, 104, 0, 0, 0, 0, + 0, 0, 0, 0, 144, 4, 174, 0, 4, 23, 30, 99, 113, 4, 175, 0, + 4, 4, 4, 4, 113, 15, 176, 158, 4, 177, 4, 178, 179, 180, 4, 96, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 103, 99, 166, 181, 182, 0, 0, + 183, 184, 99, 103, 100, 0, 0, 185, 99, 160, 0, 0, 4, 186, 0, 0, + 187, 99, 0, 144, 144, 0, 75, 188, 4, 99, 99, 145, 94, 0, 0, 0, + 4, 4, 14, 0, 4, 145, 4, 145, 4, 111, 25, 189, 110, 0, 0, 0, + 0, 0, 0, 0, 4, 190, 191, 0, 144, 192, 110, 15, 57, 15, 188, 103, + 108, 193, 0, 194, 108, 22, 15, 14, 108, 68, 195, 196, 108, 145, 197, 0, + 198, 199, 74, 0, 200, 201, 100, 0, 49, 46, 202, 57, 203, 204, 205, 0, + 4, 104, 206, 57, 4, 22, 207, 0, 0, 0, 0, 0, 4, 131, 208, 0, + 4, 22, 209, 0, 4, 210, 0, 0, 89, 0, 68, 0, 0, 0, 0, 0, + 4, 211, 0, 0, 0, 4, 4, 212, 213, 214, 215, 0, 0, 216, 174, 217, + 218, 219, 220, 4, 221, 15, 4, 29, 0, 0, 0, 0, 0, 0, 4, 74, + 222, 131, 74, 139, 22, 0, 0, 0, 223, 174, 224, 225, 226, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 145, 227, 96, 0, 0, 0, 47, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 160, 0, 0, 0, + 4, 4, 4, 131, 4, 4, 4, 4, 4, 4, 111, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 4, 4, 174, + 4, 22, 228, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 89, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 113, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 29, 100, 15, 4, 100, 15, 229, 4, 22, 111, 230, 22, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 76, 0, 0, 0, 0, + 0, 0, 4, 4, 0, 0, 0, 0, 4, 4, 231, 0, 164, 0, 0, 232, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 193, + 4, 4, 4, 4, 4, 4, 99, 212, 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 234, 235, 236, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 158, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 237, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 239, 4, 240, 241, 242, 4, 243, 244, 245, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 246, 247, 83, 239, 239, 248, 248, 222, 222, 148, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 100, 249, 0, 0, 0, 0, 0, 0, + 0, 15, 4, 229, 0, 0, 0, 0, 4, 250, 251, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 15, 229, 4, 211, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 15, 211, 0, 0, 0, 0, 0, 0, 15, 252, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253, + 4, 4, 4, 4, 4, 4, 188, 0, 4, 4, 254, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 242, 255, 256, 257, 258, 259, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 160, 4, 4, 4, 4, 4, 4, + 113, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 260, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 261, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 113, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 113, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 30, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 22, 0, 0 +}; + +static RE_UINT8 re_xid_start_table_3[] = { + 0, 0, 0, 0, 254, 255, 255, 7, 0, 4, 32, 4, 255, 255, 127, 255, + 255, 255, 255, 255, 195, 255, 3, 0, 31, 80, 0, 0, 0, 0, 223, 184, + 64, 215, 255, 255, 251, 255, 255, 255, 255, 255, 191, 255, 3, 252, 255, 255, + 255, 255, 254, 255, 255, 255, 127, 2, 255, 1, 0, 0, 0, 0, 255, 255, + 255, 135, 7, 0, 255, 7, 0, 0, 0, 192, 254, 255, 255, 255, 47, 0, + 96, 192, 0, 156, 0, 0, 253, 255, 255, 255, 0, 0, 0, 224, 255, 255, + 63, 0, 2, 0, 0, 252, 255, 255, 255, 7, 48, 4, 255, 255, 63, 4, + 16, 1, 0, 0, 255, 255, 255, 1, 255, 7, 255, 255, 255, 126, 0, 0, + 255, 3, 0, 0, 240, 255, 255, 255, 255, 255, 255, 35, 0, 0, 1, 255, + 3, 0, 254, 255, 225, 159, 249, 255, 255, 253, 197, 35, 0, 64, 0, 176, + 3, 0, 3, 16, 224, 135, 249, 255, 255, 253, 109, 3, 0, 0, 0, 94, + 0, 0, 28, 0, 224, 191, 251, 255, 255, 253, 237, 35, 0, 0, 1, 0, + 3, 0, 0, 2, 224, 159, 249, 255, 0, 0, 0, 176, 3, 0, 2, 0, + 232, 199, 61, 214, 24, 199, 255, 3, 224, 223, 253, 255, 255, 253, 255, 35, + 0, 0, 0, 39, 3, 0, 0, 0, 225, 223, 253, 255, 255, 253, 239, 35, + 0, 0, 0, 96, 3, 0, 6, 0, 240, 223, 253, 255, 255, 255, 255, 39, + 0, 64, 112, 128, 3, 0, 0, 252, 224, 255, 127, 252, 255, 255, 251, 47, + 127, 0, 0, 0, 254, 255, 255, 255, 255, 255, 5, 0, 214, 247, 255, 255, + 175, 255, 5, 32, 95, 0, 0, 240, 1, 0, 0, 0, 255, 254, 255, 255, + 255, 31, 0, 0, 0, 31, 0, 0, 255, 7, 0, 128, 0, 0, 63, 60, + 98, 192, 225, 255, 3, 64, 0, 0, 191, 32, 255, 255, 255, 255, 255, 247, + 255, 61, 127, 61, 255, 61, 255, 255, 255, 255, 61, 127, 61, 255, 127, 255, + 255, 255, 61, 255, 255, 255, 255, 7, 255, 255, 63, 63, 255, 159, 255, 255, + 255, 199, 255, 1, 255, 255, 3, 128, 255, 255, 3, 0, 255, 223, 1, 0, + 255, 255, 15, 0, 0, 0, 128, 16, 255, 5, 255, 255, 255, 255, 63, 0, + 255, 255, 255, 127, 255, 63, 31, 0, 255, 15, 255, 255, 255, 255, 127, 0, + 255, 255, 31, 0, 128, 0, 0, 0, 224, 255, 255, 255, 224, 31, 0, 0, + 248, 255, 255, 255, 1, 192, 0, 252, 63, 0, 0, 0, 15, 0, 0, 0, + 0, 224, 0, 252, 255, 255, 255, 63, 255, 255, 255, 231, 0, 222, 111, 4, + 63, 63, 255, 170, 255, 255, 223, 95, 220, 31, 207, 15, 255, 31, 220, 31, + 0, 0, 2, 128, 0, 0, 255, 31, 132, 252, 47, 63, 80, 253, 255, 243, + 224, 67, 0, 0, 31, 120, 12, 0, 255, 128, 0, 0, 127, 127, 127, 127, + 224, 0, 0, 0, 254, 3, 62, 31, 255, 255, 127, 224, 255, 127, 0, 0, + 255, 31, 255, 255, 0, 12, 0, 0, 255, 127, 0, 128, 0, 0, 128, 255, + 252, 255, 255, 255, 255, 249, 255, 255, 255, 63, 235, 31, 0, 0, 252, 255, + 187, 247, 255, 255, 7, 0, 0, 0, 0, 0, 252, 104, 63, 0, 255, 255, + 255, 255, 255, 31, 255, 255, 7, 0, 0, 128, 0, 0, 223, 255, 0, 124, + 247, 15, 0, 0, 255, 255, 127, 196, 255, 255, 98, 62, 5, 0, 0, 56, + 255, 7, 28, 0, 126, 126, 126, 0, 127, 127, 255, 255, 255, 3, 255, 255, + 15, 0, 255, 255, 127, 248, 255, 255, 255, 255, 255, 15, 255, 63, 255, 255, + 255, 255, 255, 3, 127, 0, 248, 160, 255, 253, 127, 95, 219, 255, 255, 255, + 0, 0, 248, 255, 255, 255, 252, 255, 255, 0, 0, 0, 0, 0, 255, 3, + 0, 0, 138, 170, 192, 255, 255, 255, 252, 252, 252, 28, 255, 239, 255, 255, + 127, 255, 255, 183, 255, 63, 255, 63, 255, 255, 1, 0, 15, 255, 62, 0, + 255, 255, 15, 255, 255, 0, 255, 255, 15, 0, 255, 247, 255, 247, 183, 255, + 251, 255, 251, 27, 191, 255, 255, 255, 255, 255, 253, 7, 63, 253, 255, 255, + 255, 255, 191, 145, 255, 255, 55, 0, 255, 255, 255, 192, 1, 0, 239, 254, + 31, 0, 0, 0, 63, 128, 255, 255, 255, 3, 3, 0, 28, 0, 0, 0, + 128, 0, 255, 255, 255, 255, 255, 0, 0, 0, 38, 0, 144, 0, 255, 255, + 255, 255, 71, 0, 30, 0, 0, 20, 255, 255, 251, 255, 255, 15, 0, 128, + 127, 189, 255, 191, 255, 1, 255, 255, 0, 0, 1, 224, 255, 75, 255, 255, + 255, 255, 191, 0, 0, 0, 10, 0, 128, 7, 0, 128, 176, 0, 0, 0, + 0, 0, 0, 15, 16, 0, 0, 0, 255, 7, 0, 1, 255, 15, 0, 0, + 0, 0, 0, 128, 127, 242, 111, 255, 255, 255, 0, 128, 2, 0, 0, 0, + 255, 252, 255, 255, 10, 0, 0, 0, 1, 248, 255, 255, 255, 255, 7, 4, + 0, 0, 1, 240, 255, 3, 0, 32, 255, 253, 255, 255, 127, 251, 255, 255, + 64, 0, 0, 0, 191, 253, 255, 255, 255, 3, 0, 1, 244, 255, 253, 255, + 126, 0, 0, 0, 255, 63, 0, 0, 248, 255, 255, 224, 255, 7, 1, 0, + 11, 0, 0, 0, 0, 0, 239, 111, 7, 0, 4, 0, 0, 0, 39, 0, + 240, 0, 255, 255, 255, 7, 255, 31, 255, 1, 255, 3, 255, 255, 223, 255, + 255, 255, 255, 223, 100, 222, 255, 235, 239, 255, 255, 255, 191, 231, 223, 223, + 255, 255, 255, 123, 95, 252, 253, 255, 63, 255, 255, 255, 253, 255, 255, 247, + 255, 127, 255, 255, 224, 7, 0, 0, 255, 31, 128, 63, 0, 64, 0, 0, + 255, 63, 1, 0, 127, 111, 255, 127, 15, 8, 0, 0, 150, 254, 247, 10, + 132, 234, 150, 170, 150, 247, 247, 94, 255, 251, 255, 15, 238, 251, 255, 15, + 3, 0, 255, 255, 1, 0, 255, 255 +}; + +RE_UINT32 re_get_xid_start(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 offset; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = (codepoint >> 3) & 0x3; + offset = codepoint & 0x7; + + v = re_xid_start_table_1[field_2]; + v = re_xid_start_table_2[(v << 5) | field_1]; + v = re_xid_start_table_3[(v << 2) | field_0]; + + return (v >> offset) & 0x1; +} + +/* All cases. */ +static RE_UINT8 re_all_cases_table_1[] = { + 0, 1, 2, 2, 3, 2, 2, 4, 5, 6, 2, 7, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 8, 9, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 10, 11, + 2, 12, 2, 13, 2, 2, 14, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 15, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 +}; + +static RE_UINT8 re_all_cases_table_2[] = { + 0, 0, 1, 2, 0, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 6, 14, 15, 16, 17, 0, 0, 0, 0, 0, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 6, 29, 6, 6, 30, 31, 32, 33, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 34, 35, 36, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 38, 39, + 0, 0, 0, 0, 40, 36, 0, 0, 0, 0, 0, 41, 42, 0, 0, 0, + 6, 6, 6, 43, 44, 6, 6, 6, 45, 46, 47, 48, 46, 49, 50, 51, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 53, 54, 55, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 56, 57, 58, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 59, 60, 61, 62, 6, 6, 6, 63, 34, 64, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 65, 66, 67, 0, 0, 0, 0, 68, 6, 69, 70, 71, 72, 73, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, 75, 76, 77, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 78, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 79, 0, 0, 0, 0, 0, + 80, 81, 82, 0, 0, 83, 84, 85, 0, 0, 0, 86, 87, 88, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 89, 90, 89, 90, 0, 0, 91, 92, 93, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 94, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 95, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 96, 97, 98, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_all_cases_table_3[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 152, 1, 3, 1, 1, 1, 1, + 1, 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 3, 1, 1, 1, 1, + 1, 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 163, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 83, + 1, 1, 1, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 29, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 151, 15, 16, 16, 16, 16, 16, 16, 0, 23, 23, 25, 25, 23, 23, 27, + 27, 23, 23, 25, 25, 23, 23, 28, 28, 0, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 29, 23, 23, 25, 25, 23, 23, 154, + 53, 30, 16, 16, 16, 16, 30, 28, 28, 31, 32, 25, 25, 0, 33, 34, + 35, 23, 23, 36, 37, 47, 38, 38, 16, 16, 51, 125, 36, 39, 49, 40, + 16, 16, 16, 16, 16, 16, 41, 28, 28, 42, 0, 0, 16, 16, 41, 43, + 43, 44, 45, 25, 25, 23, 23, 46, 16, 16, 0, 0, 16, 16, 0, 48, + 0, 0, 0, 0, 173, 173, 24, 167, 167, 17, 174, 174, 26, 23, 23, 43, + 43, 23, 23, 25, 25, 23, 23, 28, 28, 23, 23, 25, 25, 33, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 0, 168, 168, 18, 16, 16, 47, 48, 16, 16, 16, 16, 16, 16, 16, 16, + 49, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 50, 25, 25, 51, 52, 110, + 108, 23, 23, 53, 54, 55, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 108, 106, 109, 30, 30, 0, 31, 32, 0, 34, 0, 35, 114, 0, 0, 0, + 36, 115, 0, 37, 124, 112, 113, 0, 38, 38, 117, 103, 116, 0, 0, 36, + 0, 107, 39, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 105, 0, 0, + 41, 0, 122, 42, 0, 0, 0, 119, 41, 54, 44, 45, 55, 0, 0, 0, + 0, 0, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 118, 0, + 0, 0, 0, 0, 0, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 16, 16, 16, 0, 0, 16, 16, 0, 0, 0, 75, 76, 76, 0, 56, + 0, 0, 0, 0, 0, 0, 57, 0, 58, 59, 58, 0, 60, 0, 61, 62, + 87, 1, 6, 1, 1, 7, 1, 1, 8, 160, 10, 1, 163, 1, 1, 1, + 63, 64, 0, 169, 65, 65, 66, 65, 65, 67, 65, 65, 57, 58, 59, 58, + 89, 1, 6, 1, 1, 7, 1, 1, 8, 9, 10, 1, 11, 1, 1, 1, + 63, 64, 169, 19, 65, 65, 66, 65, 65, 67, 65, 65, 60, 61, 62, 71, + 156, 158, 0, 0, 0, 177, 175, 71, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 162, 176, 74, 56, 159, 157, 0, 28, 28, 74, 16, 16, 0, 75, 76, 76, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 1, 1, 12, 1, 13, 1, 1, 1, 1, 1, 1, 1, 1, 1, 14, 1, + 65, 68, 69, 65, 65, 65, 65, 65, 65, 65, 70, 65, 65, 65, 65, 65, + 1, 1, 12, 1, 13, 1, 1, 1, 1, 1, 1, 1, 1, 1, 14, 1, + 65, 68, 69, 65, 65, 65, 65, 65, 65, 65, 70, 65, 65, 65, 65, 65, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 16, 16, 20, 20, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 28, 23, 23, 25, 25, 23, 23, 28, 28, 23, 23, 25, 25, 23, 23, 28, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 0, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 78, 78, 78, 78, 78, 78, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 78, 78, 78, 78, 78, 78, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, + 80, 80, 80, 80, 80, 80, 0, 80, 0, 0, 0, 0, 0, 80, 0, 0, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 0, 0, 82, 82, 82, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 81, 81, 81, 81, 81, 81, 0, 0, 81, 81, 81, 81, 81, 81, 0, 0, + 164, 165, 166, 179, 180, 181, 182, 170, 172, 23, 23, 0, 0, 0, 0, 0, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 0, 0, 0, 104, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 21, 21, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 171, 0, 0, 83, 0, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 0, 0, 81, 81, 81, 81, 81, 81, 0, 0, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 0, 0, 81, 81, 81, 81, 81, 81, 0, 0, + 0, 81, 0, 81, 0, 81, 0, 81, 0, 81, 0, 81, 0, 81, 0, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 84, 84, 85, 85, 86, 86, 88, 88, 92, 92, 90, 90, 75, 75, 0, 0, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 0, 28, 0, 0, 0, 0, 81, 81, 84, 84, 28, 0, 161, 0, + 0, 0, 0, 28, 0, 0, 0, 0, 85, 85, 86, 86, 28, 0, 0, 0, + 81, 81, 0, 87, 0, 0, 0, 0, 81, 81, 88, 88, 0, 0, 0, 0, + 81, 81, 0, 89, 0, 91, 0, 0, 81, 81, 90, 90, 91, 0, 0, 0, + 0, 0, 0, 28, 0, 0, 0, 0, 92, 92, 75, 75, 28, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 178, 0, 0, 0, 153, 155, 0, 0, 0, 0, + 0, 0, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 0, 0, 0, 25, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 95, 95, 96, 96, 97, 97, 96, 96, 95, 95, + 98, 98, 99, 99, 98, 98, 100, 100, 57, 57, 101, 101, 57, 57, 100, 100, + 95, 95, 96, 96, 97, 97, 96, 96, 95, 95, 98, 98, 99, 99, 98, 98, + 100, 100, 57, 57, 101, 101, 57, 57, 100, 100, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 16, 16, 103, 104, 105, 50, 52, 28, 28, 23, 23, 25, 25, 106, 107, 108, + 109, 0, 16, 16, 0, 23, 23, 0, 0, 0, 0, 0, 0, 0, 110, 108, + 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 25, 25, 23, 23, 0, + 0, 0, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 80, 80, 80, 80, 80, 80, 0, 80, 0, 0, 0, 0, 0, 80, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 172, 22, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, + 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 23, 25, 25, 111, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 25, 25, 112, 0, 0, + 16, 16, 16, 16, 77, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 113, 114, 115, 116, 117, 0, + 118, 119, 120, 121, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 77, 122, 123, 28, 28, 23, 23, 124, 16, 16, 0, 0, + 16, 16, 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, 125, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 0, 0, 0, 0, 0, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 0, 0, 0, 0, 0, + 130, 130, 130, 130, 130, 130, 130, 130, 131, 131, 131, 131, 131, 131, 131, 131, + 130, 130, 130, 130, 130, 130, 130, 130, 132, 132, 132, 132, 132, 132, 132, 132, + 133, 133, 133, 133, 133, 133, 133, 133, 130, 130, 130, 130, 130, 130, 130, 130, + 131, 131, 131, 131, 131, 131, 131, 131, 130, 130, 130, 130, 130, 130, 130, 130, + 132, 132, 132, 132, 132, 132, 132, 132, 133, 133, 133, 133, 133, 133, 133, 133, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 133, 133, 133, 133, 133, 133, 133, 133, 132, 132, 132, 132, 132, 132, 132, 132, + 130, 130, 130, 130, 130, 130, 130, 130, 131, 131, 131, 131, 131, 131, 131, 131, + 130, 130, 130, 130, 0, 0, 0, 0, 133, 133, 133, 133, 133, 133, 133, 133, + 132, 132, 132, 132, 132, 132, 132, 132, 130, 130, 130, 130, 130, 130, 130, 130, + 131, 131, 131, 131, 131, 131, 131, 131, 130, 130, 130, 130, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 134, 135, 136, 135, 137, 135, 136, 135, 134, 138, 139, 0, 140, 138, 139, 138, + 59, 141, 142, 141, 143, 141, 142, 141, 59, 144, 145, 0, 146, 144, 145, 144, + 59, 141, 142, 0, 143, 141, 0, 134, 135, 136, 135, 137, 135, 136, 135, 134, + 138, 139, 0, 140, 138, 139, 138, 59, 141, 142, 141, 143, 141, 142, 141, 59, + 144, 145, 0, 146, 144, 145, 144, 59, 141, 142, 0, 143, 141, 0, 0, 0, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 147, 147, 147, 147, 147, 147, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 147, 147, 147, 147, 147, 147, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 148, 148, 100, 100, 148, 148, 101, 101, 148, 148, 100, 100, 148, 148, 149, 149, + 148, 148, 100, 100, 148, 148, 101, 101, 148, 148, 100, 100, 148, 148, 150, 150, + 72, 72, 148, 148, 100, 100, 148, 148, 101, 101, 148, 148, 100, 100, 148, 148, + 149, 149, 148, 148, 100, 100, 148, 148, 101, 101, 148, 148, 100, 100, 148, 148, + 150, 150, 72, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_AllCases re_all_cases_table_4[] = { + { 0, { 0, 0}}, + { 32, { 0, 0}}, + { 32, { 304, 0}}, + { 32, { 8490, 0}}, + { 32, { 383, 0}}, + { 32, { 8491, 0}}, + { 32, { 976, 0}}, + { 32, { 1013, 0}}, + { 32, { 977, 1012}}, + { 252, { 921, 8126}}, + { 32, { 1008, 0}}, + { 777, { 924, 0}}, + { 32, { 7296, 0}}, + { 32, { 7297, 0}}, + { 32, { 7298, 0}}, + { 376, { 0, 0}}, + { 1, { 0, 0}}, + { 14, { 456, 0}}, + { 2, { 498, 0}}, + { 96, { 962, 0}}, + { 1, { 7303, 0}}, + { 1, { 7835, 0}}, + {47811, {42570, 0}}, + { 3, { 0, 0}}, + { 2, { 453, 0}}, + { 7, { 0, 0}}, + { 6, { 459, 0}}, + { 127, { 0, 0}}, + { 15, { 0, 0}}, + { 391, { 0, 0}}, + { 978, { 0, 0}}, + { 991, { 0, 0}}, + { 989, { 0, 0}}, + { 83, { 0, 0}}, + { 982, { 0, 0}}, + { 971, { 0, 0}}, + { 1011, { 0, 0}}, + { 1015, { 0, 0}}, + { 1023, { 0, 0}}, + { 1007, { 0, 0}}, + { 1002, { 0, 0}}, + { 806, { 0, 0}}, + { 810, { 0, 0}}, + { 31, { 0, 0}}, + { 827, { 0, 0}}, + { 825, { 0, 0}}, + { 805, { 0, 0}}, + { 99, { 0, 0}}, + { 72, { 0, 0}}, + { 958, { 0, 0}}, + {11871, { 0, 0}}, + { 935, { 0, 0}}, + {11864, { 0, 0}}, + { 963, { 0, 0}}, + { 205, { 0, 0}}, + { 201, { 0, 0}}, + { 140, { 0, 0}}, + { 42, { 0, 0}}, + { 37, { 0, 0}}, + { 39, { 0, 0}}, + { 64, { 0, 0}}, + { 67, { 0, 0}}, + { 65, { 0, 0}}, + { 96, { 982, 0}}, + { 96, { 1009, 0}}, + { 96, { 0, 0}}, + { 96, { 981, 0}}, + { 96, { 8486, 0}}, + { 96, { 7299, 0}}, + { 96, { 7300, 7301}}, + { 96, { 7302, 0}}, + { 24, { 0, 0}}, + { 98, { 0, 0}}, + { 48, { 0, 0}}, + { 11, { 0, 0}}, + { 134, { 0, 0}}, + { 130, { 0, 0}}, + { 80, { 0, 0}}, + { 208, { 0, 0}}, + {15776, { 0, 0}}, + {15840, { 0, 0}}, + { 8, { 0, 0}}, + { 3136, { 0, 0}}, + { 7745, { 0, 0}}, + { 202, { 0, 0}}, + { 186, { 0, 0}}, + { 190, { 0, 0}}, + { 7235, { 0, 0}}, + { 172, { 0, 0}}, + { 7251, { 0, 0}}, + { 144, { 0, 0}}, + { 9, { 0, 0}}, + { 128, { 0, 0}}, + { 124, { 0, 0}}, + { 16, { 0, 0}}, + { 102, { 0, 0}}, + { 106, { 0, 0}}, + { 110, { 0, 0}}, + { 26, { 0, 0}}, + { 30, { 0, 0}}, + { 38, { 0, 0}}, + { 46, { 0, 0}}, + { 112, { 0, 0}}, + {11785, { 0, 0}}, + {12574, { 0, 0}}, + {11801, { 0, 0}}, + {11836, { 0, 0}}, + {11807, { 0, 0}}, + {11839, { 0, 0}}, + {11810, { 0, 0}}, + {11841, { 0, 0}}, + {47620, { 0, 0}}, + {42472, { 0, 0}}, + {42444, { 0, 0}}, + {42487, { 0, 0}}, + {42445, { 0, 0}}, + {42433, { 0, 0}}, + {42436, { 0, 0}}, + {42286, { 0, 0}}, + {42294, { 0, 0}}, + {42287, { 0, 0}}, + { 3296, { 0, 0}}, + {42311, { 0, 0}}, + {47688, { 0, 0}}, + {42415, { 0, 0}}, + {42567, { 0, 0}}, + {47312, { 0, 0}}, + {47152, { 0, 0}}, + {47184, { 0, 0}}, + {47216, { 0, 0}}, + { 40, { 0, 0}}, + { 56, { 0, 0}}, + { 88, { 0, 0}}, + { 104, { 0, 0}}, + { 231, { 0, 0}}, + { 233, { 0, 0}}, + { 235, { 0, 0}}, + { 239, { 0, 0}}, + { 217, { 0, 0}}, + { 219, { 0, 0}}, + { 223, { 0, 0}}, + { 41, { 0, 0}}, + { 43, { 0, 0}}, + { 47, { 0, 0}}, + { 57, { 0, 0}}, + { 59, { 0, 0}}, + { 63, { 0, 0}}, + { 224, { 0, 0}}, + { 34, { 0, 0}}, + { 62, { 0, 0}}, + { 94, { 0, 0}}, + { 345, { 0, 0}}, + { 32, { 305, 0}}, + { 8545, { 107, 0}}, + { 300, { 115, 0}}, + { 8686, { 229, 0}}, + { 66, { 946, 0}}, + { 96, { 949, 0}}, + { 73, { 952, 1012}}, + { 108, { 952, 977}}, + { 220, { 953, 8126}}, + { 7419, { 921, 953}}, + { 106, { 954, 0}}, + { 809, { 956, 0}}, + { 6290, { 1074, 0}}, + { 6293, { 1076, 0}}, + { 6300, { 1086, 0}}, + { 15, { 457, 0}}, + { 3, { 499, 0}}, + { 97, { 963, 0}}, + { 6373, { 1123, 0}}, + { 251, { 7777, 0}}, + {47810, {42571, 0}}, + { 1, { 454, 0}}, + { 1, { 460, 0}}, + { 118, { 960, 0}}, + { 80, { 961, 0}}, + { 115, { 966, 0}}, + { 8847, { 969, 0}}, + { 6306, { 1089, 0}}, + { 6310, { 1090, 7301}}, + { 6311, { 1090, 7300}}, + { 6316, { 1098, 0}} +}; + +int re_get_all_cases(RE_UINT32 codepoint, RE_UINT32* cases) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = codepoint & 0x1F; + + v = re_all_cases_table_1[field_2]; + v = re_all_cases_table_2[(v << 5) | field_1]; + v = re_all_cases_table_3[(v << 5) | field_0]; + + cases[0] = codepoint; + + if (re_all_cases_table_4[v].delta == 0) + return 1; + + cases[1] = codepoint ^ re_all_cases_table_4[v].delta; + + if (re_all_cases_table_4[v].others[0] == 0) + return 2; + + cases[2] = re_all_cases_table_4[v].others[0]; + + if (re_all_cases_table_4[v].others[1] == 0) + return 3; + + cases[3] = re_all_cases_table_4[v].others[1]; + + return 4; +} + +/* Simple case folding. */ +static RE_UINT8 re_simple_folding_table_1[] = { + 0, 1, 2, 2, 3, 2, 2, 4, 5, 6, 2, 7, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 8, 9, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 10, 11, + 2, 12, 2, 13, 2, 2, 14, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 15, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 +}; + +static RE_UINT8 re_simple_folding_table_2[] = { + 0, 0, 1, 0, 0, 2, 3, 0, 4, 5, 6, 7, 8, 9, 10, 11, + 4, 12, 13, 0, 0, 0, 0, 0, 0, 0, 14, 15, 16, 17, 18, 19, + 20, 21, 0, 4, 22, 4, 23, 4, 4, 24, 25, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 26, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, + 0, 0, 0, 0, 29, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 31, 4, 4, 4, 32, 33, 34, 35, 33, 36, 37, 38, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 0, 40, 41, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 42, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 44, 45, 0, 46, 4, 4, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 48, 49, 0, 0, 0, 0, 50, 4, 51, 52, 53, 54, 55, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 57, 58, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 59, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, + 61, 62, 0, 0, 0, 63, 64, 0, 0, 0, 0, 65, 66, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 67, 68, 0, 0, 0, 0, 69, 70, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 73, 74, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_simple_folding_table_3[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 18, 18, 18, 18, 18, 18, 18, 18, 80, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 0, 18, 18, 18, 18, 18, 18, 18, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 79, 0, 1, 0, 1, 0, 1, 0, 0, 3, 0, 5, 0, 3, 0, 55, + 0, 3, 0, 5, 0, 3, 0, 10, 0, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 81, 3, 0, 5, 0, 3, 0, 78, + 0, 92, 1, 0, 1, 0, 92, 10, 0, 95, 94, 5, 0, 0, 42, 93, + 91, 3, 0, 98, 99, 0, 100, 100, 1, 0, 0, 0, 98, 97, 0, 96, + 1, 0, 1, 0, 1, 0, 84, 10, 0, 85, 0, 0, 1, 0, 84, 17, + 0, 87, 86, 5, 0, 3, 0, 83, 1, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 2, 3, 0, 9, 1, 0, 4, 5, 0, 3, 0, 17, + 0, 3, 0, 5, 0, 3, 0, 10, 0, 3, 0, 5, 0, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 0, 2, 1, 0, 1, 0, 47, 38, 1, 0, 1, 0, 1, 0, 1, 0, + 89, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 126, 5, 0, 88, 125, 0, + 0, 3, 0, 90, 66, 64, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 59, + 0, 0, 0, 0, 0, 0, 25, 0, 20, 22, 20, 0, 35, 0, 37, 36, + 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 45, 45, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, + 46, 50, 0, 0, 0, 12, 13, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 39, 29, 0, 0, 40, 35, 0, 10, 0, 8, 1, 0, 0, 58, 57, 57, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 10, 3, 0, 5, 0, 3, 0, 10, 0, 3, 0, 5, 0, 3, 0, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 0, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 67, 67, 67, 67, 67, 67, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 129, 129, 129, 129, 129, 129, 0, 129, 0, 0, 0, 0, 0, 129, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 0, 0, + 103, 104, 105, 106, 107, 108, 109, 110, 148, 3, 0, 0, 0, 0, 0, 0, + 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, + 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, + 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 0, 0, 101, 101, 101, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 76, 0, 0, 114, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 6, 0, 6, 0, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 65, 65, 10, 0, 111, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 62, 62, 63, 63, 10, 0, 0, 0, + 0, 0, 0, 112, 0, 0, 0, 0, 6, 6, 61, 61, 0, 0, 0, 0, + 0, 0, 0, 113, 0, 0, 0, 0, 6, 6, 60, 60, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 56, 56, 58, 58, 10, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 117, 0, 0, 0, 115, 116, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 48, 48, 51, 51, 52, 52, 51, 51, 48, 48, + 15, 15, 16, 16, 15, 15, 21, 21, 25, 25, 27, 27, 25, 25, 21, 21, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 118, 127, 119, 0, 0, 10, 0, 3, 0, 5, 0, 122, 120, 123, + 121, 0, 1, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 124, 123, + 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 3, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 5, 0, 146, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 5, 0, 139, 0, 0, + 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 137, 140, 138, 135, 136, 0, + 130, 132, 131, 102, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 41, 133, 147, 10, 0, 3, 0, 134, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 141, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, + 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, + 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, + 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 0, 0, 0, 0, + 23, 23, 23, 23, 23, 23, 23, 23, 30, 30, 30, 30, 30, 30, 30, 30, + 23, 23, 23, 23, 23, 23, 23, 23, 43, 43, 43, 43, 43, 43, 43, 43, + 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 49, 49, 49, 49, 49, 49, 49, 49, 43, 43, 43, 43, 43, 43, 43, 43, + 23, 23, 23, 23, 23, 23, 23, 23, 30, 30, 30, 30, 30, 30, 30, 30, + 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 72, 73, 74, 73, 75, 73, 74, 73, 72, 68, 69, 0, 70, 68, 69, 68, + 22, 24, 26, 24, 28, 24, 26, 24, 22, 31, 32, 0, 34, 31, 32, 31, + 22, 24, 26, 0, 28, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 19, 19, 21, 21, 19, 19, 27, 27, 19, 19, 21, 21, 19, 19, 33, 33, + 19, 19, 21, 21, 19, 19, 27, 27, 19, 19, 21, 21, 19, 19, 44, 44, + 46, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT16 re_simple_folding_table_4[] = { + 0, 1, 2, 3, 6, 7, 8, 9, + 11, 14, 15, 16, 19, 22, 24, 26, + 30, 31, 32, 34, 37, 38, 39, 40, + 41, 42, 43, 46, 47, 48, 56, 57, + 59, 62, 63, 64, 65, 67, 72, 74, + 76, 80, 83, 88, 94, 96, 98, 99, + 102, 104, 105, 106, 110, 112, 124, 127, + 128, 130, 134, 140, 144, 172, 186, 190, + 201, 202, 205, 208, 217, 219, 223, 224, + 231, 233, 235, 239, 250, 252, 268, 345, + 376, 391, 777, 805, 806, 810, 825, 827, + 935, 958, 963, 971, 978, 982, 989, 991, + 1002, 1007, 1011, 1015, 1023, 3136, 3296, 6322, + 6325, 6332, 6338, 6342, 6343, 6348, 6372, 7175, + 7235, 7251, 7745, 8513, 8654, 8943, 11785, 11801, + 11807, 11810, 11836, 11839, 11841, 11864, 11871, 12574, + 15776, 15840, 42286, 42287, 42294, 42311, 42415, 42433, + 42436, 42444, 42445, 42472, 42487, 42567, 47152, 47184, + 47216, 47312, 47620, 47688, 47811 +}; + +RE_UINT32 re_get_simple_case_folding(RE_UINT32 codepoint) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 v; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = codepoint & 0x1F; + + v = re_simple_folding_table_1[field_2]; + v = re_simple_folding_table_2[(v << 5) | field_1]; + v = re_simple_folding_table_3[(v << 5) | field_0]; + + return codepoint ^ re_simple_folding_table_4[v]; +} + +/* Full case folding. */ +static RE_UINT8 re_full_folding_table_1[] = { + 0, 1, 2, 2, 3, 2, 2, 4, 5, 6, 2, 7, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 8, 9, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 10, 11, + 2, 12, 2, 13, 2, 2, 14, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 15, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 +}; + +static RE_UINT8 re_full_folding_table_2[] = { + 0, 0, 1, 0, 0, 2, 3, 0, 4, 5, 6, 7, 8, 9, 10, 11, + 4, 12, 13, 0, 0, 0, 0, 0, 0, 0, 14, 15, 16, 17, 18, 19, + 20, 21, 0, 4, 22, 4, 23, 4, 4, 24, 25, 0, 26, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 27, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, + 0, 0, 0, 0, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 32, 4, 4, 4, 33, 34, 35, 36, 37, 38, 39, 40, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 42, 43, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 44, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 46, 47, 0, 48, 4, 4, 4, 49, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 50, 51, 0, 0, 0, 0, 52, 4, 53, 54, 55, 56, 57, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, 59, 60, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 61, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 0, 0, 0, + 63, 64, 0, 0, 0, 65, 66, 0, 0, 0, 0, 67, 68, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 69, 70, 0, 0, 0, 0, 71, 72, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 75, 76, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_UINT8 re_full_folding_table_3[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 18, 18, 18, 18, 18, 18, 18, 18, 94, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 97, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 0, 18, 18, 18, 18, 18, 18, 18, 67, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 93, 0, 1, 0, 1, 0, 1, 0, 0, 3, 0, 5, 0, 3, 0, 57, + 0, 3, 0, 5, 0, 3, 0, 10, 0, 114, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 95, 3, 0, 5, 0, 3, 0, 91, + 0, 107, 1, 0, 1, 0, 107, 10, 0, 110, 109, 5, 0, 0, 43, 108, + 106, 3, 0, 113, 115, 0, 116, 116, 1, 0, 0, 0, 113, 112, 0, 111, + 1, 0, 1, 0, 1, 0, 99, 10, 0, 100, 0, 0, 1, 0, 99, 17, + 0, 102, 101, 5, 0, 3, 0, 98, 1, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 2, 3, 0, 9, 1, 0, 4, 5, 0, 3, 0, 17, + 0, 3, 0, 5, 0, 3, 0, 10, 0, 3, 0, 5, 0, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 96, 2, 1, 0, 1, 0, 48, 39, 1, 0, 1, 0, 1, 0, 1, 0, + 104, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 172, 5, 0, 103, 171, 0, + 0, 3, 0, 105, 78, 76, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 0, 0, 0, 26, 0, 20, 22, 20, 0, 36, 0, 38, 37, + 25, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 46, 46, 0, 46, 46, 46, 46, 46, 46, 46, 46, 46, 0, 0, 0, 0, + 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, + 47, 51, 0, 0, 0, 12, 13, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 40, 30, 0, 0, 41, 36, 0, 10, 0, 8, 1, 0, 0, 61, 60, 60, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 10, 3, 0, 5, 0, 3, 0, 10, 0, 3, 0, 5, 0, 3, 0, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 79, 79, 79, 79, 79, 79, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 175, 175, 175, 175, 175, 175, 0, 175, 0, 0, 0, 0, 0, 175, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 0, 0, + 119, 120, 121, 122, 123, 124, 125, 126, 194, 3, 0, 0, 0, 0, 0, 0, + 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, + 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, + 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 0, 0, 117, 117, 117, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 160, 156, 158, 155, 159, 89, 0, 0, 157, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 0, 0, + 153, 0, 154, 0, 151, 0, 152, 0, 0, 6, 0, 6, 0, 6, 0, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 59, 59, 59, 59, 59, 59, 59, 59, 62, 62, 62, 62, 62, 62, 62, 62, + 68, 68, 68, 68, 68, 68, 68, 68, 70, 70, 70, 70, 70, 70, 70, 70, + 73, 73, 73, 73, 73, 73, 73, 73, 75, 75, 75, 75, 75, 75, 75, 75, + 0, 0, 74, 127, 132, 0, 130, 128, 6, 6, 77, 77, 131, 0, 129, 0, + 0, 0, 69, 149, 143, 0, 148, 147, 71, 71, 72, 72, 150, 0, 0, 0, + 0, 0, 144, 142, 0, 0, 146, 145, 6, 6, 66, 66, 0, 0, 0, 0, + 0, 0, 137, 136, 135, 0, 134, 133, 6, 6, 65, 65, 7, 0, 0, 0, + 0, 0, 64, 139, 139, 0, 141, 140, 58, 58, 61, 61, 138, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 163, 0, 0, 0, 161, 162, 0, 0, 0, 0, + 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 49, 49, 52, 52, 53, 53, 52, 52, 49, 49, + 15, 15, 16, 16, 15, 15, 21, 21, 26, 26, 28, 28, 26, 26, 21, 21, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 164, 173, 165, 0, 0, 10, 0, 3, 0, 5, 0, 168, 166, 169, + 167, 0, 1, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 170, 169, + 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 3, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 5, 0, 192, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 5, 0, 185, 0, 0, + 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 183, 186, 184, 181, 182, 0, + 176, 178, 177, 118, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 42, 179, 193, 10, 0, 3, 0, 180, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 187, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, + 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, + 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, + 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, + 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, + 198, 199, 196, 197, 195, 201, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 205, 202, 203, 206, 204, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 0, 0, 0, 0, 0, + 23, 23, 23, 23, 23, 23, 23, 23, 31, 31, 31, 31, 31, 31, 31, 31, + 23, 23, 23, 23, 23, 23, 23, 23, 44, 44, 44, 44, 44, 44, 44, 44, + 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 50, 50, 50, 50, 50, 50, 50, 50, 44, 44, 44, 44, 44, 44, 44, 44, + 23, 23, 23, 23, 23, 23, 23, 23, 31, 31, 31, 31, 31, 31, 31, 31, + 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 85, 86, 87, 86, 88, 86, 87, 86, 85, 80, 81, 0, 82, 80, 81, 80, + 22, 24, 27, 24, 29, 24, 27, 24, 22, 32, 33, 0, 35, 32, 33, 32, + 22, 24, 27, 0, 29, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 83, 83, 83, 83, 83, 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 19, 19, 21, 21, 19, 19, 28, 28, 19, 19, 21, 21, 19, 19, 34, 34, + 19, 19, 21, 21, 19, 19, 28, 28, 19, 19, 21, 21, 19, 19, 45, 45, + 47, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static RE_FullCaseFolding re_full_folding_table_4[] = { + {{ 0, 0, 0}}, + {{ 1, 0, 0}}, + {{ 2, 0, 0}}, + {{ 3, 0, 0}}, + {{ 6, 0, 0}}, + {{ 7, 0, 0}}, + {{ 8, 0, 0}}, + {{ 9, 0, 0}}, + {{ 11, 0, 0}}, + {{ 14, 0, 0}}, + {{ 15, 0, 0}}, + {{ 16, 0, 0}}, + {{ 19, 0, 0}}, + {{ 22, 0, 0}}, + {{ 24, 0, 0}}, + {{ 26, 0, 0}}, + {{ 30, 0, 0}}, + {{ 31, 0, 0}}, + {{ 32, 0, 0}}, + {{ 34, 0, 0}}, + {{ 37, 0, 0}}, + {{ 38, 0, 0}}, + {{ 39, 0, 0}}, + {{ 40, 0, 0}}, + {{ 41, 0, 0}}, + {{ 41, 776, 769}}, + {{ 42, 0, 0}}, + {{ 43, 0, 0}}, + {{ 46, 0, 0}}, + {{ 47, 0, 0}}, + {{ 48, 0, 0}}, + {{ 56, 0, 0}}, + {{ 57, 0, 0}}, + {{ 59, 0, 0}}, + {{ 62, 0, 0}}, + {{ 63, 0, 0}}, + {{ 64, 0, 0}}, + {{ 65, 0, 0}}, + {{ 67, 0, 0}}, + {{ 72, 0, 0}}, + {{ 74, 0, 0}}, + {{ 76, 0, 0}}, + {{ 80, 0, 0}}, + {{ 83, 0, 0}}, + {{ 88, 0, 0}}, + {{ 94, 0, 0}}, + {{ 96, 0, 0}}, + {{ 98, 0, 0}}, + {{ 99, 0, 0}}, + {{ 102, 0, 0}}, + {{ 104, 0, 0}}, + {{ 105, 0, 0}}, + {{ 106, 0, 0}}, + {{ 110, 0, 0}}, + {{ 112, 0, 0}}, + {{ 117, 776, 769}}, + {{ 124, 0, 0}}, + {{ 127, 0, 0}}, + {{ 128, 0, 0}}, + {{ 128, 953, 0}}, + {{ 130, 0, 0}}, + {{ 134, 0, 0}}, + {{ 136, 953, 0}}, + {{ 140, 0, 0}}, + {{ 142, 953, 0}}, + {{ 144, 0, 0}}, + {{ 172, 0, 0}}, + {{ 172, 115, 0}}, + {{ 176, 953, 0}}, + {{ 182, 953, 0}}, + {{ 184, 953, 0}}, + {{ 186, 0, 0}}, + {{ 190, 0, 0}}, + {{ 192, 953, 0}}, + {{ 194, 953, 0}}, + {{ 200, 953, 0}}, + {{ 201, 0, 0}}, + {{ 202, 0, 0}}, + {{ 205, 0, 0}}, + {{ 208, 0, 0}}, + {{ 217, 0, 0}}, + {{ 219, 0, 0}}, + {{ 223, 0, 0}}, + {{ 224, 0, 0}}, + {{ 226, 1410, 0}}, + {{ 231, 0, 0}}, + {{ 233, 0, 0}}, + {{ 235, 0, 0}}, + {{ 239, 0, 0}}, + {{ 250, 0, 0}}, + {{ 252, 0, 0}}, + {{ 268, 0, 0}}, + {{ 345, 0, 0}}, + {{ 345, 775, 0}}, + {{ 376, 0, 0}}, + {{ 391, 0, 0}}, + {{ 410, 780, 0}}, + {{ 777, 0, 0}}, + {{ 805, 0, 0}}, + {{ 806, 0, 0}}, + {{ 810, 0, 0}}, + {{ 825, 0, 0}}, + {{ 827, 0, 0}}, + {{ 935, 0, 0}}, + {{ 958, 0, 0}}, + {{ 963, 0, 0}}, + {{ 971, 0, 0}}, + {{ 978, 0, 0}}, + {{ 982, 0, 0}}, + {{ 989, 0, 0}}, + {{ 991, 0, 0}}, + {{ 1002, 0, 0}}, + {{ 1007, 0, 0}}, + {{ 1011, 0, 0}}, + {{ 1013, 110, 0}}, + {{ 1015, 0, 0}}, + {{ 1023, 0, 0}}, + {{ 3136, 0, 0}}, + {{ 3296, 0, 0}}, + {{ 6322, 0, 0}}, + {{ 6325, 0, 0}}, + {{ 6332, 0, 0}}, + {{ 6338, 0, 0}}, + {{ 6342, 0, 0}}, + {{ 6343, 0, 0}}, + {{ 6348, 0, 0}}, + {{ 6372, 0, 0}}, + {{ 7170, 953, 0}}, + {{ 7174, 834, 953}}, + {{ 7175, 0, 0}}, + {{ 7175, 834, 0}}, + {{ 7181, 953, 0}}, + {{ 7192, 953, 0}}, + {{ 7202, 776, 834}}, + {{ 7203, 834, 0}}, + {{ 7205, 787, 0}}, + {{ 7206, 776, 769}}, + {{ 7207, 776, 768}}, + {{ 7221, 953, 0}}, + {{ 7226, 953, 0}}, + {{ 7230, 834, 953}}, + {{ 7231, 834, 0}}, + {{ 7274, 776, 769}}, + {{ 7274, 953, 0}}, + {{ 7275, 776, 768}}, + {{ 7278, 776, 834}}, + {{ 7279, 834, 0}}, + {{ 7280, 834, 953}}, + {{ 7281, 834, 0}}, + {{ 7284, 953, 0}}, + {{ 7291, 953, 0}}, + {{ 7313, 787, 769}}, + {{ 7315, 787, 834}}, + {{ 7317, 787, 0}}, + {{ 7319, 787, 768}}, + {{ 7904, 778, 0}}, + {{ 7907, 776, 0}}, + {{ 7917, 115, 0}}, + {{ 7919, 778, 0}}, + {{ 7931, 702, 0}}, + {{ 7934, 817, 0}}, + {{ 8513, 0, 0}}, + {{ 8654, 0, 0}}, + {{ 8943, 0, 0}}, + {{11785, 0, 0}}, + {{11801, 0, 0}}, + {{11807, 0, 0}}, + {{11810, 0, 0}}, + {{11836, 0, 0}}, + {{11839, 0, 0}}, + {{11841, 0, 0}}, + {{11864, 0, 0}}, + {{11871, 0, 0}}, + {{12574, 0, 0}}, + {{15776, 0, 0}}, + {{15840, 0, 0}}, + {{42286, 0, 0}}, + {{42287, 0, 0}}, + {{42294, 0, 0}}, + {{42311, 0, 0}}, + {{42415, 0, 0}}, + {{42433, 0, 0}}, + {{42436, 0, 0}}, + {{42444, 0, 0}}, + {{42445, 0, 0}}, + {{42472, 0, 0}}, + {{42487, 0, 0}}, + {{42567, 0, 0}}, + {{47152, 0, 0}}, + {{47184, 0, 0}}, + {{47216, 0, 0}}, + {{47312, 0, 0}}, + {{47620, 0, 0}}, + {{47688, 0, 0}}, + {{47811, 0, 0}}, + {{64354, 102, 108}}, + {{64356, 108, 0}}, + {{64357, 102, 105}}, + {{64358, 102, 0}}, + {{64359, 105, 0}}, + {{64373, 116, 0}}, + {{64374, 116, 0}}, + {{65120, 1381, 0}}, + {{65121, 1387, 0}}, + {{65123, 1389, 0}}, + {{65127, 1398, 0}}, + {{65128, 1398, 0}} +}; + +int re_get_full_case_folding(RE_UINT32 codepoint, RE_UINT32* folded) { + RE_UINT32 field_2; + RE_UINT32 field_1; + RE_UINT32 field_0; + RE_UINT32 v; + RE_UINT16* data; + + field_2 = codepoint >> 10; + field_1 = (codepoint >> 5) & 0x1F; + field_0 = codepoint & 0x1F; + + v = re_full_folding_table_1[field_2]; + v = re_full_folding_table_2[(v << 5) | field_1]; + v = re_full_folding_table_3[(v << 5) | field_0]; + + data = re_full_folding_table_4[v].data; + folded[0] = codepoint ^ data[0]; + + if (data[1] == 0) + return 1; + + folded[1] = data[1]; + + if (data[2] == 0) + return 2; + + folded[2] = data[2]; + + return 3; +} + +/* Property function table. */ +RE_GetPropertyFunc re_get_property[] = { + re_get_alphabetic, + re_get_alphanumeric, + re_get_any, + re_get_ascii_hex_digit, + re_get_bidi_class, + re_get_bidi_control, + re_get_bidi_mirrored, + re_get_blank, + re_get_block, + re_get_canonical_combining_class, + re_get_cased, + re_get_case_ignorable, + re_get_changes_when_casefolded, + re_get_changes_when_casemapped, + re_get_changes_when_lowercased, + re_get_changes_when_titlecased, + re_get_changes_when_uppercased, + re_get_dash, + re_get_decomposition_type, + re_get_default_ignorable_code_point, + re_get_deprecated, + re_get_diacritic, + re_get_east_asian_width, + re_get_emoji, + re_get_emoji_component, + re_get_emoji_modifier, + re_get_emoji_modifier_base, + re_get_emoji_presentation, + re_get_extended_pictographic, + re_get_extender, + re_get_general_category, + re_get_graph, + re_get_grapheme_base, + re_get_grapheme_cluster_break, + re_get_grapheme_extend, + re_get_grapheme_link, + re_get_hangul_syllable_type, + re_get_hex_digit, + re_get_horiz_space, + re_get_hyphen, + re_get_id_compat_math_continue, + re_get_id_compat_math_start, + re_get_id_continue, + re_get_ideographic, + re_get_ids_binary_operator, + re_get_id_start, + re_get_ids_trinary_operator, + re_get_ids_unary_operator, + re_get_indic_conjunct_break, + re_get_indic_positional_category, + re_get_indic_syllabic_category, + re_get_join_control, + re_get_joining_group, + re_get_joining_type, + re_get_line_break, + re_get_logical_order_exception, + re_get_lowercase, + re_get_math, + re_get_modifier_combining_mark, + re_get_nfc_quick_check, + re_get_nfd_quick_check, + re_get_nfkc_quick_check, + re_get_nfkd_quick_check, + re_get_noncharacter_code_point, + re_get_numeric_type, + re_get_numeric_value, + re_get_other_alphabetic, + re_get_other_default_ignorable_code_point, + re_get_other_grapheme_extend, + re_get_other_id_continue, + re_get_other_id_start, + re_get_other_lowercase, + re_get_other_math, + re_get_other_uppercase, + re_get_pattern_syntax, + re_get_pattern_white_space, + re_get_posix_alnum, + re_get_posix_digit, + re_get_posix_punct, + re_get_posix_xdigit, + re_get_prepended_concatenation_mark, + re_get_print, + re_get_quotation_mark, + re_get_radical, + re_get_regional_indicator, + re_get_script, + 0, + re_get_sentence_break, + re_get_sentence_terminal, + re_get_soft_dotted, + re_get_terminal_punctuation, + re_get_unified_ideograph, + re_get_uppercase, + re_get_variation_selector, + re_get_vert_space, + re_get_white_space, + re_get_word, + re_get_word_break, + re_get_xdigit, + re_get_xid_continue, + re_get_xid_start +}; \ No newline at end of file diff --git a/third_party/mrabarnett/_regex_unicode.h b/third_party/mrabarnett/_regex_unicode.h new file mode 100644 index 000000000..81d901966 --- /dev/null +++ b/third_party/mrabarnett/_regex_unicode.h @@ -0,0 +1,315 @@ +typedef unsigned char RE_UINT8; +typedef signed char RE_INT8; +typedef unsigned short RE_UINT16; +typedef signed short RE_INT16; +typedef unsigned int RE_UINT32; +typedef signed int RE_INT32; + +typedef unsigned char BOOL; +#if !defined(FALSE) || !defined(TRUE) +#define FALSE 0 +#define TRUE 1 +#endif + +#define RE_ASCII_MAX 0x7F +#define RE_LOCALE_MAX 0xFF + +#define RE_MAX_CASES 4 +#define RE_MAX_FOLDED 3 +#define RE_MAX_SCX 23 + +typedef struct RE_Property { + RE_UINT16 name; + RE_UINT8 id; + RE_UINT8 value_set; +} RE_Property; + +typedef struct RE_PropertyValue { + RE_UINT16 name; + RE_UINT8 value_set; + RE_UINT16 id; +} RE_PropertyValue; + +typedef RE_UINT32 (*RE_GetPropertyFunc)(RE_UINT32 codepoint); + +#define RE_PROP_GC 0x1E +#define RE_PROP_CASED 0xA +#define RE_PROP_UPPERCASE 0x5C +#define RE_PROP_LOWERCASE 0x38 +#define RE_PROP_SCX 0x56 + +#define RE_PROP_C 30 +#define RE_PROP_L 31 +#define RE_PROP_M 32 +#define RE_PROP_N 33 +#define RE_PROP_P 34 +#define RE_PROP_S 35 +#define RE_PROP_Z 36 +#define RE_PROP_ASSIGNED 37 +#define RE_PROP_CASEDLETTER 38 + +#define RE_PROP_CN 0 +#define RE_PROP_CC 1 +#define RE_PROP_ZS 2 +#define RE_PROP_PO 3 +#define RE_PROP_SC 4 +#define RE_PROP_PS 5 +#define RE_PROP_PE 6 +#define RE_PROP_SM 7 +#define RE_PROP_PD 8 +#define RE_PROP_ND 9 +#define RE_PROP_LU 10 +#define RE_PROP_SK 11 +#define RE_PROP_PC 12 +#define RE_PROP_LL 13 +#define RE_PROP_SO 14 +#define RE_PROP_LO 15 +#define RE_PROP_PI 16 +#define RE_PROP_CF 17 +#define RE_PROP_NO 18 +#define RE_PROP_PF 19 +#define RE_PROP_LT 20 +#define RE_PROP_LM 21 +#define RE_PROP_MN 22 +#define RE_PROP_ME 23 +#define RE_PROP_MC 24 +#define RE_PROP_NL 25 +#define RE_PROP_ZL 26 +#define RE_PROP_ZP 27 +#define RE_PROP_CS 28 +#define RE_PROP_CO 29 + +#define RE_PROP_C_MASK 0x30020003 +#define RE_PROP_L_MASK 0x0030A400 +#define RE_PROP_M_MASK 0x01C00000 +#define RE_PROP_N_MASK 0x02040200 +#define RE_PROP_P_MASK 0x00091168 +#define RE_PROP_S_MASK 0x00004890 +#define RE_PROP_Z_MASK 0x0C000004 + +#define RE_PROP_ALNUM 0x010001 +#define RE_PROP_ALPHA 0x000001 +#define RE_PROP_ANY 0x020001 +#define RE_PROP_ASCII 0x080001 +#define RE_PROP_BLANK 0x070001 +#define RE_PROP_CNTRL 0x1E0001 +#define RE_PROP_DIGIT 0x1E0009 +#define RE_PROP_GRAPH 0x1F0001 +#define RE_PROP_LOWER 0x380001 +#define RE_PROP_PRINT 0x510001 +#define RE_PROP_SPACE 0x5F0001 +#define RE_PROP_UPPER 0x5C0001 +#define RE_PROP_WORD 0x600001 +#define RE_PROP_XDIGIT 0x620001 +#define RE_PROP_POSIX_ALNUM 0x4C0001 +#define RE_PROP_POSIX_DIGIT 0x4D0001 +#define RE_PROP_POSIX_PUNCT 0x4E0001 +#define RE_PROP_POSIX_XDIGIT 0x4F0001 + +#define RE_WBREAK_OTHER 0 +#define RE_WBREAK_LF 1 +#define RE_WBREAK_NEWLINE 2 +#define RE_WBREAK_CR 3 +#define RE_WBREAK_WSEGSPACE 4 +#define RE_WBREAK_DOUBLEQUOTE 5 +#define RE_WBREAK_SINGLEQUOTE 6 +#define RE_WBREAK_MIDNUM 7 +#define RE_WBREAK_MIDNUMLET 8 +#define RE_WBREAK_NUMERIC 9 +#define RE_WBREAK_MIDLETTER 10 +#define RE_WBREAK_ALETTER 11 +#define RE_WBREAK_EXTENDNUMLET 12 +#define RE_WBREAK_FORMAT 13 +#define RE_WBREAK_EXTEND 14 +#define RE_WBREAK_HEBREWLETTER 15 +#define RE_WBREAK_ZWJ 16 +#define RE_WBREAK_KATAKANA 17 +#define RE_WBREAK_REGIONALINDICATOR 18 +#define RE_WBREAK_EBASE 19 +#define RE_WBREAK_EBASEGAZ 20 +#define RE_WBREAK_EMODIFIER 21 +#define RE_WBREAK_GLUEAFTERZWJ 22 + +#define RE_GBREAK_OTHER 0 +#define RE_GBREAK_CONTROL 1 +#define RE_GBREAK_LF 2 +#define RE_GBREAK_CR 3 +#define RE_GBREAK_EXTEND 4 +#define RE_GBREAK_PREPEND 5 +#define RE_GBREAK_SPACINGMARK 6 +#define RE_GBREAK_L 7 +#define RE_GBREAK_V 8 +#define RE_GBREAK_T 9 +#define RE_GBREAK_ZWJ 10 +#define RE_GBREAK_LV 11 +#define RE_GBREAK_LVT 12 +#define RE_GBREAK_REGIONALINDICATOR 13 +#define RE_GBREAK_EBASE 14 +#define RE_GBREAK_EBASEGAZ 15 +#define RE_GBREAK_EMODIFIER 16 +#define RE_GBREAK_GLUEAFTERZWJ 17 + +#define RE_LBREAK_UNKNOWN 0 +#define RE_LBREAK_COMBININGMARK 1 +#define RE_LBREAK_BREAKAFTER 2 +#define RE_LBREAK_LINEFEED 3 +#define RE_LBREAK_MANDATORYBREAK 4 +#define RE_LBREAK_CARRIAGERETURN 5 +#define RE_LBREAK_SPACE 6 +#define RE_LBREAK_EXCLAMATION 7 +#define RE_LBREAK_QUOTATION 8 +#define RE_LBREAK_ALPHABETIC 9 +#define RE_LBREAK_PREFIXNUMERIC 10 +#define RE_LBREAK_POSTFIXNUMERIC 11 +#define RE_LBREAK_OPENPUNCTUATION 12 +#define RE_LBREAK_CLOSEPARENTHESIS 13 +#define RE_LBREAK_INFIXNUMERIC 14 +#define RE_LBREAK_HYPHEN 15 +#define RE_LBREAK_BREAKSYMBOLS 16 +#define RE_LBREAK_NUMERIC 17 +#define RE_LBREAK_CLOSEPUNCTUATION 18 +#define RE_LBREAK_NEXTLINE 19 +#define RE_LBREAK_GLUE 20 +#define RE_LBREAK_AMBIGUOUS 21 +#define RE_LBREAK_BREAKBEFORE 22 +#define RE_LBREAK_HEBREWLETTER 23 +#define RE_LBREAK_COMPLEXCONTEXT 24 +#define RE_LBREAK_JL 25 +#define RE_LBREAK_JV 26 +#define RE_LBREAK_JT 27 +#define RE_LBREAK_NONSTARTER 28 +#define RE_LBREAK_AKSARA 29 +#define RE_LBREAK_VIRAMA 30 +#define RE_LBREAK_AKSARASTART 31 +#define RE_LBREAK_IDEOGRAPHIC 32 +#define RE_LBREAK_VIRAMAFINAL 33 +#define RE_LBREAK_ZWSPACE 34 +#define RE_LBREAK_ZWJ 35 +#define RE_LBREAK_BREAKBOTH 36 +#define RE_LBREAK_INSEPARABLE 37 +#define RE_LBREAK_WORDJOINER 38 +#define RE_LBREAK_EBASE 39 +#define RE_LBREAK_CONDITIONALJAPANESESTARTER 40 +#define RE_LBREAK_H2 41 +#define RE_LBREAK_H3 42 +#define RE_LBREAK_SURROGATE 43 +#define RE_LBREAK_CONTINGENTBREAK 44 +#define RE_LBREAK_AKSARAPREBASE 45 +#define RE_LBREAK_REGIONALINDICATOR 46 +#define RE_LBREAK_EMODIFIER 47 + +#define RE_INCB_NONE 0 +#define RE_INCB_EXTEND 1 +#define RE_INCB_CONSONANT 2 +#define RE_INCB_LINKER 3 + +extern char* re_strings[1530]; +extern RE_Property re_properties[185]; +extern RE_PropertyValue re_property_values[1680]; +extern RE_UINT16 re_expand_on_folding[104]; +extern RE_GetPropertyFunc re_get_property[101]; + +RE_UINT32 re_get_alphabetic(RE_UINT32 codepoint); +RE_UINT32 re_get_alphanumeric(RE_UINT32 codepoint); +RE_UINT32 re_get_any(RE_UINT32 codepoint); +RE_UINT32 re_get_ascii_hex_digit(RE_UINT32 codepoint); +RE_UINT32 re_get_bidi_class(RE_UINT32 codepoint); +RE_UINT32 re_get_bidi_control(RE_UINT32 codepoint); +RE_UINT32 re_get_bidi_mirrored(RE_UINT32 codepoint); +RE_UINT32 re_get_blank(RE_UINT32 codepoint); +RE_UINT32 re_get_block(RE_UINT32 codepoint); +RE_UINT32 re_get_canonical_combining_class(RE_UINT32 codepoint); +RE_UINT32 re_get_cased(RE_UINT32 codepoint); +RE_UINT32 re_get_case_ignorable(RE_UINT32 codepoint); +RE_UINT32 re_get_changes_when_casefolded(RE_UINT32 codepoint); +RE_UINT32 re_get_changes_when_casemapped(RE_UINT32 codepoint); +RE_UINT32 re_get_changes_when_lowercased(RE_UINT32 codepoint); +RE_UINT32 re_get_changes_when_titlecased(RE_UINT32 codepoint); +RE_UINT32 re_get_changes_when_uppercased(RE_UINT32 codepoint); +RE_UINT32 re_get_dash(RE_UINT32 codepoint); +RE_UINT32 re_get_decomposition_type(RE_UINT32 codepoint); +RE_UINT32 re_get_default_ignorable_code_point(RE_UINT32 codepoint); +RE_UINT32 re_get_deprecated(RE_UINT32 codepoint); +RE_UINT32 re_get_diacritic(RE_UINT32 codepoint); +RE_UINT32 re_get_east_asian_width(RE_UINT32 codepoint); +RE_UINT32 re_get_emoji(RE_UINT32 codepoint); +RE_UINT32 re_get_emoji_component(RE_UINT32 codepoint); +RE_UINT32 re_get_emoji_modifier(RE_UINT32 codepoint); +RE_UINT32 re_get_emoji_modifier_base(RE_UINT32 codepoint); +RE_UINT32 re_get_emoji_presentation(RE_UINT32 codepoint); +RE_UINT32 re_get_extended_pictographic(RE_UINT32 codepoint); +RE_UINT32 re_get_extender(RE_UINT32 codepoint); +RE_UINT32 re_get_general_category(RE_UINT32 codepoint); +RE_UINT32 re_get_graph(RE_UINT32 codepoint); +RE_UINT32 re_get_grapheme_base(RE_UINT32 codepoint); +RE_UINT32 re_get_grapheme_cluster_break(RE_UINT32 codepoint); +RE_UINT32 re_get_grapheme_extend(RE_UINT32 codepoint); +RE_UINT32 re_get_grapheme_link(RE_UINT32 codepoint); +RE_UINT32 re_get_hangul_syllable_type(RE_UINT32 codepoint); +RE_UINT32 re_get_hex_digit(RE_UINT32 codepoint); +RE_UINT32 re_get_horiz_space(RE_UINT32 codepoint); +RE_UINT32 re_get_hyphen(RE_UINT32 codepoint); +RE_UINT32 re_get_id_compat_math_continue(RE_UINT32 codepoint); +RE_UINT32 re_get_id_compat_math_start(RE_UINT32 codepoint); +RE_UINT32 re_get_id_continue(RE_UINT32 codepoint); +RE_UINT32 re_get_ideographic(RE_UINT32 codepoint); +RE_UINT32 re_get_ids_binary_operator(RE_UINT32 codepoint); +RE_UINT32 re_get_id_start(RE_UINT32 codepoint); +RE_UINT32 re_get_ids_trinary_operator(RE_UINT32 codepoint); +RE_UINT32 re_get_ids_unary_operator(RE_UINT32 codepoint); +RE_UINT32 re_get_indic_conjunct_break(RE_UINT32 codepoint); +RE_UINT32 re_get_indic_positional_category(RE_UINT32 codepoint); +RE_UINT32 re_get_indic_syllabic_category(RE_UINT32 codepoint); +RE_UINT32 re_get_join_control(RE_UINT32 codepoint); +RE_UINT32 re_get_joining_group(RE_UINT32 codepoint); +RE_UINT32 re_get_joining_type(RE_UINT32 codepoint); +RE_UINT32 re_get_line_break(RE_UINT32 codepoint); +RE_UINT32 re_get_logical_order_exception(RE_UINT32 codepoint); +RE_UINT32 re_get_lowercase(RE_UINT32 codepoint); +RE_UINT32 re_get_math(RE_UINT32 codepoint); +RE_UINT32 re_get_modifier_combining_mark(RE_UINT32 codepoint); +RE_UINT32 re_get_nfc_quick_check(RE_UINT32 codepoint); +RE_UINT32 re_get_nfd_quick_check(RE_UINT32 codepoint); +RE_UINT32 re_get_nfkc_quick_check(RE_UINT32 codepoint); +RE_UINT32 re_get_nfkd_quick_check(RE_UINT32 codepoint); +RE_UINT32 re_get_noncharacter_code_point(RE_UINT32 codepoint); +RE_UINT32 re_get_numeric_type(RE_UINT32 codepoint); +RE_UINT32 re_get_numeric_value(RE_UINT32 codepoint); +RE_UINT32 re_get_other_alphabetic(RE_UINT32 codepoint); +RE_UINT32 re_get_other_default_ignorable_code_point(RE_UINT32 codepoint); +RE_UINT32 re_get_other_grapheme_extend(RE_UINT32 codepoint); +RE_UINT32 re_get_other_id_continue(RE_UINT32 codepoint); +RE_UINT32 re_get_other_id_start(RE_UINT32 codepoint); +RE_UINT32 re_get_other_lowercase(RE_UINT32 codepoint); +RE_UINT32 re_get_other_math(RE_UINT32 codepoint); +RE_UINT32 re_get_other_uppercase(RE_UINT32 codepoint); +RE_UINT32 re_get_pattern_syntax(RE_UINT32 codepoint); +RE_UINT32 re_get_pattern_white_space(RE_UINT32 codepoint); +RE_UINT32 re_get_posix_alnum(RE_UINT32 codepoint); +RE_UINT32 re_get_posix_digit(RE_UINT32 codepoint); +RE_UINT32 re_get_posix_punct(RE_UINT32 codepoint); +RE_UINT32 re_get_posix_xdigit(RE_UINT32 codepoint); +RE_UINT32 re_get_prepended_concatenation_mark(RE_UINT32 codepoint); +RE_UINT32 re_get_print(RE_UINT32 codepoint); +RE_UINT32 re_get_quotation_mark(RE_UINT32 codepoint); +RE_UINT32 re_get_radical(RE_UINT32 codepoint); +RE_UINT32 re_get_regional_indicator(RE_UINT32 codepoint); +RE_UINT32 re_get_script(RE_UINT32 codepoint); +int re_get_script_extensions(RE_UINT32 codepoint, RE_UINT8* scripts); +RE_UINT32 re_get_sentence_break(RE_UINT32 codepoint); +RE_UINT32 re_get_sentence_terminal(RE_UINT32 codepoint); +RE_UINT32 re_get_soft_dotted(RE_UINT32 codepoint); +RE_UINT32 re_get_terminal_punctuation(RE_UINT32 codepoint); +RE_UINT32 re_get_unified_ideograph(RE_UINT32 codepoint); +RE_UINT32 re_get_uppercase(RE_UINT32 codepoint); +RE_UINT32 re_get_variation_selector(RE_UINT32 codepoint); +RE_UINT32 re_get_vert_space(RE_UINT32 codepoint); +RE_UINT32 re_get_white_space(RE_UINT32 codepoint); +RE_UINT32 re_get_word(RE_UINT32 codepoint); +RE_UINT32 re_get_word_break(RE_UINT32 codepoint); +RE_UINT32 re_get_xdigit(RE_UINT32 codepoint); +RE_UINT32 re_get_xid_continue(RE_UINT32 codepoint); +RE_UINT32 re_get_xid_start(RE_UINT32 codepoint); +int re_get_all_cases(RE_UINT32 codepoint, RE_UINT32* cases); +RE_UINT32 re_get_simple_case_folding(RE_UINT32 codepoint); +int re_get_full_case_folding(RE_UINT32 codepoint, RE_UINT32* folded); \ No newline at end of file diff --git a/third_party/mrabarnett/readme.rst b/third_party/mrabarnett/readme.rst new file mode 100644 index 000000000..bf95a29a2 --- /dev/null +++ b/third_party/mrabarnett/readme.rst @@ -0,0 +1,1034 @@ +Introduction +------------ + +This regex implementation is backwards-compatible with the standard 're' module, but offers additional functionality. + +Python 2 +-------- + +Python 2 is no longer supported. The last release that supported Python 2 was 2021.11.10. + +PyPy +---- + +This module is targeted at CPython. It expects that all codepoints are the same width, so it won't behave properly with PyPy outside U+0000..U+007F because PyPy stores strings as UTF-8. + +Multithreading +-------------- + +The regex module releases the GIL during matching on instances of the built-in (immutable) string classes, enabling other Python threads to run concurrently. It is also possible to force the regex module to release the GIL during matching by calling the matching methods with the keyword argument ``concurrent=True``. The behaviour is undefined if the string changes during matching, so use it *only* when it is guaranteed that that won't happen. + +Unicode +------- + +This module supports Unicode 16.0.0. Full Unicode case-folding is supported. + +Flags +----- + +There are 2 kinds of flag: scoped and global. Scoped flags can apply to only part of a pattern and can be turned on or off; global flags apply to the entire pattern and can only be turned on. + +The scoped flags are: ``ASCII (?a)``, ``FULLCASE (?f)``, ``IGNORECASE (?i)``, ``LOCALE (?L)``, ``MULTILINE (?m)``, ``DOTALL (?s)``, ``UNICODE (?u)``, ``VERBOSE (?x)``, ``WORD (?w)``. + +The global flags are: ``BESTMATCH (?b)``, ``ENHANCEMATCH (?e)``, ``POSIX (?p)``, ``REVERSE (?r)``, ``VERSION0 (?V0)``, ``VERSION1 (?V1)``. + +If neither the ``ASCII``, ``LOCALE`` nor ``UNICODE`` flag is specified, it will default to ``UNICODE`` if the regex pattern is a Unicode string and ``ASCII`` if it's a bytestring. + +The ``ENHANCEMATCH`` flag makes fuzzy matching attempt to improve the fit of the next match that it finds. + +The ``BESTMATCH`` flag makes fuzzy matching search for the best match instead of the next match. + +Old vs new behaviour +-------------------- + +In order to be compatible with the re module, this module has 2 behaviours: + +* **Version 0** behaviour (old behaviour, compatible with the re module): + + Please note that the re module's behaviour may change over time, and I'll endeavour to match that behaviour in version 0. + + * Indicated by the ``VERSION0`` flag. + + * Zero-width matches are not handled correctly in the re module before Python 3.7. The behaviour in those earlier versions is: + + * ``.split`` won't split a string at a zero-width match. + + * ``.sub`` will advance by one character after a zero-width match. + + * Inline flags apply to the entire pattern, and they can't be turned off. + + * Only simple sets are supported. + + * Case-insensitive matches in Unicode use simple case-folding by default. + +* **Version 1** behaviour (new behaviour, possibly different from the re module): + + * Indicated by the ``VERSION1`` flag. + + * Zero-width matches are handled correctly. + + * Inline flags apply to the end of the group or pattern, and they can be turned off. + + * Nested sets and set operations are supported. + + * Case-insensitive matches in Unicode use full case-folding by default. + +If no version is specified, the regex module will default to ``regex.DEFAULT_VERSION``. + +Case-insensitive matches in Unicode +----------------------------------- + +The regex module supports both simple and full case-folding for case-insensitive matches in Unicode. Use of full case-folding can be turned on using the ``FULLCASE`` flag. Please note that this flag affects how the ``IGNORECASE`` flag works; the ``FULLCASE`` flag itself does not turn on case-insensitive matching. + +Version 0 behaviour: the flag is off by default. + +Version 1 behaviour: the flag is on by default. + +Nested sets and set operations +------------------------------ + +It's not possible to support both simple sets, as used in the re module, and nested sets at the same time because of a difference in the meaning of an unescaped ``"["`` in a set. + +For example, the pattern ``[[a-z]--[aeiou]]`` is treated in the version 0 behaviour (simple sets, compatible with the re module) as: + +* Set containing "[" and the letters "a" to "z" + +* Literal "--" + +* Set containing letters "a", "e", "i", "o", "u" + +* Literal "]" + +but in the version 1 behaviour (nested sets, enhanced behaviour) as: + +* Set which is: + + * Set containing the letters "a" to "z" + +* but excluding: + + * Set containing the letters "a", "e", "i", "o", "u" + +Version 0 behaviour: only simple sets are supported. + +Version 1 behaviour: nested sets and set operations are supported. + +Notes on named groups +--------------------- + +All groups have a group number, starting from 1. + +Groups with the same group name will have the same group number, and groups with a different group name will have a different group number. + +The same name can be used by more than one group, with later captures 'overwriting' earlier captures. All the captures of the group will be available from the ``captures`` method of the match object. + +Group numbers will be reused across different branches of a branch reset, eg. ``(?|(first)|(second))`` has only group 1. If groups have different group names then they will, of course, have different group numbers, eg. ``(?|(?Pfirst)|(?Psecond))`` has group 1 ("foo") and group 2 ("bar"). + +In the regex ``(\s+)(?|(?P[A-Z]+)|(\w+) (?P[0-9]+)`` there are 2 groups: + +* ``(\s+)`` is group 1. + +* ``(?P[A-Z]+)`` is group 2, also called "foo". + +* ``(\w+)`` is group 2 because of the branch reset. + +* ``(?P[0-9]+)`` is group 2 because it's called "foo". + +If you want to prevent ``(\w+)`` from being group 2, you need to name it (different name, different group number). + +Additional features +------------------- + +The issue numbers relate to the Python bug tracker, except where listed otherwise. + +Added ``\p{Horiz_Space}`` and ``\p{Vert_Space}`` (`GitHub issue 477 `_) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``\p{Horiz_Space}`` or ``\p{H}`` matches horizontal whitespace and ``\p{Vert_Space}`` or ``\p{V}`` matches vertical whitespace. + +Added support for lookaround in conditional pattern (`Hg issue 163 `_) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The test of a conditional pattern can be a lookaround. + +.. sourcecode:: python + + >>> regex.match(r'(?(?=\d)\d+|\w+)', '123abc') + + >>> regex.match(r'(?(?=\d)\d+|\w+)', 'abc123') + + +This is not quite the same as putting a lookaround in the first branch of a pair of alternatives. + +.. sourcecode:: python + + >>> print(regex.match(r'(?:(?=\d)\d+\b|\w+)', '123abc')) + + >>> print(regex.match(r'(?(?=\d)\d+\b|\w+)', '123abc')) + None + +In the first example, the lookaround matched, but the remainder of the first branch failed to match, and so the second branch was attempted, whereas in the second example, the lookaround matched, and the first branch failed to match, but the second branch was **not** attempted. + +Added POSIX matching (leftmost longest) (`Hg issue 150 `_) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The POSIX standard for regex is to return the leftmost longest match. This can be turned on using the ``POSIX`` flag. + +.. sourcecode:: python + + >>> # Normal matching. + >>> regex.search(r'Mr|Mrs', 'Mrs') + + >>> regex.search(r'one(self)?(selfsufficient)?', 'oneselfsufficient') + + >>> # POSIX matching. + >>> regex.search(r'(?p)Mr|Mrs', 'Mrs') + + >>> regex.search(r'(?p)one(self)?(selfsufficient)?', 'oneselfsufficient') + + +Note that it will take longer to find matches because when it finds a match at a certain position, it won't return that immediately, but will keep looking to see if there's another longer match there. + +Added ``(?(DEFINE)...)`` (`Hg issue 152 `_) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If there's no group called "DEFINE", then ... will be ignored except that any groups defined within it can be called and that the normal rules for numbering groups still apply. + +.. sourcecode:: python + + >>> regex.search(r'(?(DEFINE)(?P\d+)(?P\w+))(?&quant) (?&item)', '5 elephants') + + +Added ``(*PRUNE)``, ``(*SKIP)`` and ``(*FAIL)`` (`Hg issue 153 `_) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``(*PRUNE)`` discards the backtracking info up to that point. When used in an atomic group or a lookaround, it won't affect the enclosing pattern. + +``(*SKIP)`` is similar to ``(*PRUNE)``, except that it also sets where in the text the next attempt to match will start. When used in an atomic group or a lookaround, it won't affect the enclosing pattern. + +``(*FAIL)`` causes immediate backtracking. ``(*F)`` is a permitted abbreviation. + +Added ``\K`` (`Hg issue 151 `_) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Keeps the part of the entire match after the position where ``\K`` occurred; the part before it is discarded. + +It does not affect what groups return. + +.. sourcecode:: python + + >>> m = regex.search(r'(\w\w\K\w\w\w)', 'abcdef') + >>> m[0] + 'cde' + >>> m[1] + 'abcde' + >>> + >>> m = regex.search(r'(?r)(\w\w\K\w\w\w)', 'abcdef') + >>> m[0] + 'bc' + >>> m[1] + 'bcdef' + +Added capture subscripting for ``expandf`` and ``subf``/``subfn`` (`Hg issue 133 `_) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +You can use subscripting to get the captures of a repeated group. + +.. sourcecode:: python + + >>> m = regex.match(r"(\w)+", "abc") + >>> m.expandf("{1}") + 'c' + >>> m.expandf("{1[0]} {1[1]} {1[2]}") + 'a b c' + >>> m.expandf("{1[-1]} {1[-2]} {1[-3]}") + 'c b a' + >>> + >>> m = regex.match(r"(?P\w)+", "abc") + >>> m.expandf("{letter}") + 'c' + >>> m.expandf("{letter[0]} {letter[1]} {letter[2]}") + 'a b c' + >>> m.expandf("{letter[-1]} {letter[-2]} {letter[-3]}") + 'c b a' + +Added support for referring to a group by number using ``(?P=...)`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This is in addition to the existing ``\g<...>``. + +Fixed the handling of locale-sensitive regexes +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The ``LOCALE`` flag is intended for legacy code and has limited support. You're still recommended to use Unicode instead. + +Added partial matches (`Hg issue 102 `_) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A partial match is one that matches up to the end of string, but that string has been truncated and you want to know whether a complete match could be possible if the string had not been truncated. + +Partial matches are supported by ``match``, ``search``, ``fullmatch`` and ``finditer`` with the ``partial`` keyword argument. + +Match objects have a ``partial`` attribute, which is ``True`` if it's a partial match. + +For example, if you wanted a user to enter a 4-digit number and check it character by character as it was being entered: + +.. sourcecode:: python + + >>> pattern = regex.compile(r'\d{4}') + + >>> # Initially, nothing has been entered: + >>> print(pattern.fullmatch('', partial=True)) + + + >>> # An empty string is OK, but it's only a partial match. + >>> # The user enters a letter: + >>> print(pattern.fullmatch('a', partial=True)) + None + >>> # It'll never match. + + >>> # The user deletes that and enters a digit: + >>> print(pattern.fullmatch('1', partial=True)) + + >>> # It matches this far, but it's only a partial match. + + >>> # The user enters 2 more digits: + >>> print(pattern.fullmatch('123', partial=True)) + + >>> # It matches this far, but it's only a partial match. + + >>> # The user enters another digit: + >>> print(pattern.fullmatch('1234', partial=True)) + + >>> # It's a complete match. + + >>> # If the user enters another digit: + >>> print(pattern.fullmatch('12345', partial=True)) + None + >>> # It's no longer a match. + + >>> # This is a partial match: + >>> pattern.match('123', partial=True).partial + True + + >>> # This is a complete match: + >>> pattern.match('1233', partial=True).partial + False + +``*`` operator not working correctly with sub() (`Hg issue 106 `_) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Sometimes it's not clear how zero-width matches should be handled. For example, should ``.*`` match 0 characters directly after matching >0 characters? + +.. sourcecode:: python + + >>> regex.sub('.*', 'x', 'test') + 'xx' + >>> regex.sub('.*?', '|', 'test') + '|||||||||' + +Added ``capturesdict`` (`Hg issue 86 `_) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``capturesdict`` is a combination of ``groupdict`` and ``captures``: + +``groupdict`` returns a dict of the named groups and the last capture of those groups. + +``captures`` returns a list of all the captures of a group + +``capturesdict`` returns a dict of the named groups and lists of all the captures of those groups. + +.. sourcecode:: python + + >>> m = regex.match(r"(?:(?P\w+) (?P\d+)\n)+", "one 1\ntwo 2\nthree 3\n") + >>> m.groupdict() + {'word': 'three', 'digits': '3'} + >>> m.captures("word") + ['one', 'two', 'three'] + >>> m.captures("digits") + ['1', '2', '3'] + >>> m.capturesdict() + {'word': ['one', 'two', 'three'], 'digits': ['1', '2', '3']} + +Added ``allcaptures`` and ``allspans`` (`Git issue 474 `_) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``allcaptures`` returns a list of all the captures of all the groups. + +``allspans`` returns a list of all the spans of the all captures of all the groups. + +.. sourcecode:: python + + >>> m = regex.match(r"(?:(?P\w+) (?P\d+)\n)+", "one 1\ntwo 2\nthree 3\n") + >>> m.allcaptures() + (['one 1\ntwo 2\nthree 3\n'], ['one', 'two', 'three'], ['1', '2', '3']) + >>> m.allspans() + ([(0, 20)], [(0, 3), (6, 9), (12, 17)], [(4, 5), (10, 11), (18, 19)]) + +Allow duplicate names of groups (`Hg issue 87 `_) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Group names can be duplicated. + +.. sourcecode:: python + + >>> # With optional groups: + >>> + >>> # Both groups capture, the second capture 'overwriting' the first. + >>> m = regex.match(r"(?P\w+)? or (?P\w+)?", "first or second") + >>> m.group("item") + 'second' + >>> m.captures("item") + ['first', 'second'] + >>> # Only the second group captures. + >>> m = regex.match(r"(?P\w+)? or (?P\w+)?", " or second") + >>> m.group("item") + 'second' + >>> m.captures("item") + ['second'] + >>> # Only the first group captures. + >>> m = regex.match(r"(?P\w+)? or (?P\w+)?", "first or ") + >>> m.group("item") + 'first' + >>> m.captures("item") + ['first'] + >>> + >>> # With mandatory groups: + >>> + >>> # Both groups capture, the second capture 'overwriting' the first. + >>> m = regex.match(r"(?P\w*) or (?P\w*)?", "first or second") + >>> m.group("item") + 'second' + >>> m.captures("item") + ['first', 'second'] + >>> # Again, both groups capture, the second capture 'overwriting' the first. + >>> m = regex.match(r"(?P\w*) or (?P\w*)", " or second") + >>> m.group("item") + 'second' + >>> m.captures("item") + ['', 'second'] + >>> # And yet again, both groups capture, the second capture 'overwriting' the first. + >>> m = regex.match(r"(?P\w*) or (?P\w*)", "first or ") + >>> m.group("item") + '' + >>> m.captures("item") + ['first', ''] + +Added ``fullmatch`` (`issue #16203 `_) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``fullmatch`` behaves like ``match``, except that it must match all of the string. + +.. sourcecode:: python + + >>> print(regex.fullmatch(r"abc", "abc").span()) + (0, 3) + >>> print(regex.fullmatch(r"abc", "abcx")) + None + >>> print(regex.fullmatch(r"abc", "abcx", endpos=3).span()) + (0, 3) + >>> print(regex.fullmatch(r"abc", "xabcy", pos=1, endpos=4).span()) + (1, 4) + >>> + >>> regex.match(r"a.*?", "abcd").group(0) + 'a' + >>> regex.fullmatch(r"a.*?", "abcd").group(0) + 'abcd' + +Added ``subf`` and ``subfn`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``subf`` and ``subfn`` are alternatives to ``sub`` and ``subn`` respectively. When passed a replacement string, they treat it as a format string. + +.. sourcecode:: python + + >>> regex.subf(r"(\w+) (\w+)", "{0} => {2} {1}", "foo bar") + 'foo bar => bar foo' + >>> regex.subf(r"(?P\w+) (?P\w+)", "{word2} {word1}", "foo bar") + 'bar foo' + +Added ``expandf`` to match object +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``expandf`` is an alternative to ``expand``. When passed a replacement string, it treats it as a format string. + +.. sourcecode:: python + + >>> m = regex.match(r"(\w+) (\w+)", "foo bar") + >>> m.expandf("{0} => {2} {1}") + 'foo bar => bar foo' + >>> + >>> m = regex.match(r"(?P\w+) (?P\w+)", "foo bar") + >>> m.expandf("{word2} {word1}") + 'bar foo' + +Detach searched string +^^^^^^^^^^^^^^^^^^^^^^ + +A match object contains a reference to the string that was searched, via its ``string`` attribute. The ``detach_string`` method will 'detach' that string, making it available for garbage collection, which might save valuable memory if that string is very large. + +.. sourcecode:: python + + >>> m = regex.search(r"\w+", "Hello world") + >>> print(m.group()) + Hello + >>> print(m.string) + Hello world + >>> m.detach_string() + >>> print(m.group()) + Hello + >>> print(m.string) + None + +Recursive patterns (`Hg issue 27 `_) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Recursive and repeated patterns are supported. + +``(?R)`` or ``(?0)`` tries to match the entire regex recursively. ``(?1)``, ``(?2)``, etc, try to match the relevant group. + +``(?&name)`` tries to match the named group. + +.. sourcecode:: python + + >>> regex.match(r"(Tarzan|Jane) loves (?1)", "Tarzan loves Jane").groups() + ('Tarzan',) + >>> regex.match(r"(Tarzan|Jane) loves (?1)", "Jane loves Tarzan").groups() + ('Jane',) + + >>> m = regex.search(r"(\w)(?:(?R)|(\w?))\1", "kayak") + >>> m.group(0, 1, 2) + ('kayak', 'k', None) + +The first two examples show how the subpattern within the group is reused, but is _not_ itself a group. In other words, ``"(Tarzan|Jane) loves (?1)"`` is equivalent to ``"(Tarzan|Jane) loves (?:Tarzan|Jane)"``. + +It's possible to backtrack into a recursed or repeated group. + +You can't call a group if there is more than one group with that group name or group number (``"ambiguous group reference"``). + +The alternative forms ``(?P>name)`` and ``(?P&name)`` are also supported. + +Full Unicode case-folding is supported +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In version 1 behaviour, the regex module uses full case-folding when performing case-insensitive matches in Unicode. + +.. sourcecode:: python + + >>> regex.match(r"(?iV1)strasse", "stra\N{LATIN SMALL LETTER SHARP S}e").span() + (0, 6) + >>> regex.match(r"(?iV1)stra\N{LATIN SMALL LETTER SHARP S}e", "STRASSE").span() + (0, 7) + +In version 0 behaviour, it uses simple case-folding for backward compatibility with the re module. + +Approximate "fuzzy" matching (`Hg issue 12 `_, `Hg issue 41 `_, `Hg issue 109 `_) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Regex usually attempts an exact match, but sometimes an approximate, or "fuzzy", match is needed, for those cases where the text being searched may contain errors in the form of inserted, deleted or substituted characters. + +A fuzzy regex specifies which types of errors are permitted, and, optionally, either the minimum and maximum or only the maximum permitted number of each type. (You cannot specify only a minimum.) + +The 3 types of error are: + +* Insertion, indicated by "i" + +* Deletion, indicated by "d" + +* Substitution, indicated by "s" + +In addition, "e" indicates any type of error. + +The fuzziness of a regex item is specified between "{" and "}" after the item. + +Examples: + +* ``foo`` match "foo" exactly + +* ``(?:foo){i}`` match "foo", permitting insertions + +* ``(?:foo){d}`` match "foo", permitting deletions + +* ``(?:foo){s}`` match "foo", permitting substitutions + +* ``(?:foo){i,s}`` match "foo", permitting insertions and substitutions + +* ``(?:foo){e}`` match "foo", permitting errors + +If a certain type of error is specified, then any type not specified will **not** be permitted. + +In the following examples I'll omit the item and write only the fuzziness: + +* ``{d<=3}`` permit at most 3 deletions, but no other types + +* ``{i<=1,s<=2}`` permit at most 1 insertion and at most 2 substitutions, but no deletions + +* ``{1<=e<=3}`` permit at least 1 and at most 3 errors + +* ``{i<=2,d<=2,e<=3}`` permit at most 2 insertions, at most 2 deletions, at most 3 errors in total, but no substitutions + +It's also possible to state the costs of each type of error and the maximum permitted total cost. + +Examples: + +* ``{2i+2d+1s<=4}`` each insertion costs 2, each deletion costs 2, each substitution costs 1, the total cost must not exceed 4 + +* ``{i<=1,d<=1,s<=1,2i+2d+1s<=4}`` at most 1 insertion, at most 1 deletion, at most 1 substitution; each insertion costs 2, each deletion costs 2, each substitution costs 1, the total cost must not exceed 4 + +You can also use "<" instead of "<=" if you want an exclusive minimum or maximum. + +You can add a test to perform on a character that's substituted or inserted. + +Examples: + +* ``{s<=2:[a-z]}`` at most 2 substitutions, which must be in the character set ``[a-z]``. + +* ``{s<=2,i<=3:\d}`` at most 2 substitutions, at most 3 insertions, which must be digits. + +By default, fuzzy matching searches for the first match that meets the given constraints. The ``ENHANCEMATCH`` flag will cause it to attempt to improve the fit (i.e. reduce the number of errors) of the match that it has found. + +The ``BESTMATCH`` flag will make it search for the best match instead. + +Further examples to note: + +* ``regex.search("(dog){e}", "cat and dog")[1]`` returns ``"cat"`` because that matches ``"dog"`` with 3 errors (an unlimited number of errors is permitted). + +* ``regex.search("(dog){e<=1}", "cat and dog")[1]`` returns ``" dog"`` (with a leading space) because that matches ``"dog"`` with 1 error, which is within the limit. + +* ``regex.search("(?e)(dog){e<=1}", "cat and dog")[1]`` returns ``"dog"`` (without a leading space) because the fuzzy search matches ``" dog"`` with 1 error, which is within the limit, and the ``(?e)`` then it attempts a better fit. + +In the first two examples there are perfect matches later in the string, but in neither case is it the first possible match. + +The match object has an attribute ``fuzzy_counts`` which gives the total number of substitutions, insertions and deletions. + +.. sourcecode:: python + + >>> # A 'raw' fuzzy match: + >>> regex.fullmatch(r"(?:cats|cat){e<=1}", "cat").fuzzy_counts + (0, 0, 1) + >>> # 0 substitutions, 0 insertions, 1 deletion. + + >>> # A better match might be possible if the ENHANCEMATCH flag used: + >>> regex.fullmatch(r"(?e)(?:cats|cat){e<=1}", "cat").fuzzy_counts + (0, 0, 0) + >>> # 0 substitutions, 0 insertions, 0 deletions. + +The match object also has an attribute ``fuzzy_changes`` which gives a tuple of the positions of the substitutions, insertions and deletions. + +.. sourcecode:: python + + >>> m = regex.search('(fuu){i<=2,d<=2,e<=5}', 'anaconda foo bar') + >>> m + + >>> m.fuzzy_changes + ([], [7, 8], [10, 11]) + +What this means is that if the matched part of the string had been: + +.. sourcecode:: python + + 'anacondfuuoo bar' + +it would've been an exact match. + +However, there were insertions at positions 7 and 8: + +.. sourcecode:: python + + 'anaconda fuuoo bar' + ^^ + +and deletions at positions 10 and 11: + +.. sourcecode:: python + + 'anaconda f~~oo bar' + ^^ + +So the actual string was: + +.. sourcecode:: python + + 'anaconda foo bar' + +Named lists ``\L`` (`Hg issue 11 `_) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +There are occasions where you may want to include a list (actually, a set) of options in a regex. + +One way is to build the pattern like this: + +.. sourcecode:: python + + >>> p = regex.compile(r"first|second|third|fourth|fifth") + +but if the list is large, parsing the resulting regex can take considerable time, and care must also be taken that the strings are properly escaped and properly ordered, for example, "cats" before "cat". + +The new alternative is to use a named list: + +.. sourcecode:: python + + >>> option_set = ["first", "second", "third", "fourth", "fifth"] + >>> p = regex.compile(r"\L", options=option_set) + +The order of the items is irrelevant, they are treated as a set. The named lists are available as the ``.named_lists`` attribute of the pattern object : + +.. sourcecode:: python + + >>> print(p.named_lists) + {'options': frozenset({'third', 'first', 'fifth', 'fourth', 'second'})} + +If there are any unused keyword arguments, ``ValueError`` will be raised unless you tell it otherwise: + +.. sourcecode:: python + + >>> option_set = ["first", "second", "third", "fourth", "fifth"] + >>> p = regex.compile(r"\L", options=option_set, other_options=[]) + Traceback (most recent call last): + File "", line 1, in + File "C:\Python310\lib\site-packages\regex\regex.py", line 353, in compile + return _compile(pattern, flags, ignore_unused, kwargs, cache_pattern) + File "C:\Python310\lib\site-packages\regex\regex.py", line 500, in _compile + complain_unused_args() + File "C:\Python310\lib\site-packages\regex\regex.py", line 483, in complain_unused_args + raise ValueError('unused keyword argument {!a}'.format(any_one)) + ValueError: unused keyword argument 'other_options' + >>> p = regex.compile(r"\L", options=option_set, other_options=[], ignore_unused=True) + >>> p = regex.compile(r"\L", options=option_set, other_options=[], ignore_unused=False) + Traceback (most recent call last): + File "", line 1, in + File "C:\Python310\lib\site-packages\regex\regex.py", line 353, in compile + return _compile(pattern, flags, ignore_unused, kwargs, cache_pattern) + File "C:\Python310\lib\site-packages\regex\regex.py", line 500, in _compile + complain_unused_args() + File "C:\Python310\lib\site-packages\regex\regex.py", line 483, in complain_unused_args + raise ValueError('unused keyword argument {!a}'.format(any_one)) + ValueError: unused keyword argument 'other_options' + >>> + +Start and end of word +^^^^^^^^^^^^^^^^^^^^^ + +``\m`` matches at the start of a word. + +``\M`` matches at the end of a word. + +Compare with ``\b``, which matches at the start or end of a word. + +Unicode line separators +^^^^^^^^^^^^^^^^^^^^^^^ + +Normally the only line separator is ``\n`` (``\x0A``), but if the ``WORD`` flag is turned on then the line separators are ``\x0D\x0A``, ``\x0A``, ``\x0B``, ``\x0C`` and ``\x0D``, plus ``\x85``, ``\u2028`` and ``\u2029`` when working with Unicode. + +This affects the regex dot ``"."``, which, with the ``DOTALL`` flag turned off, matches any character except a line separator. It also affects the line anchors ``^`` and ``$`` (in multiline mode). + +Set operators +^^^^^^^^^^^^^ + +**Version 1 behaviour only** + +Set operators have been added, and a set ``[...]`` can include nested sets. + +The operators, in order of increasing precedence, are: + +* ``||`` for union ("x||y" means "x or y") + +* ``~~`` (double tilde) for symmetric difference ("x~~y" means "x or y, but not both") + +* ``&&`` for intersection ("x&&y" means "x and y") + +* ``--`` (double dash) for difference ("x--y" means "x but not y") + +Implicit union, ie, simple juxtaposition like in ``[ab]``, has the highest precedence. Thus, ``[ab&&cd]`` is the same as ``[[a||b]&&[c||d]]``. + +Examples: + +* ``[ab]`` # Set containing 'a' and 'b' + +* ``[a-z]`` # Set containing 'a' .. 'z' + +* ``[[a-z]--[qw]]`` # Set containing 'a' .. 'z', but not 'q' or 'w' + +* ``[a-z--qw]`` # Same as above + +* ``[\p{L}--QW]`` # Set containing all letters except 'Q' and 'W' + +* ``[\p{N}--[0-9]]`` # Set containing all numbers except '0' .. '9' + +* ``[\p{ASCII}&&\p{Letter}]`` # Set containing all characters which are ASCII and letter + +regex.escape (`issue #2650 `_) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +regex.escape has an additional keyword parameter ``special_only``. When True, only 'special' regex characters, such as '?', are escaped. + +.. sourcecode:: python + + >>> regex.escape("foo!?", special_only=False) + 'foo\\!\\?' + >>> regex.escape("foo!?", special_only=True) + 'foo!\\?' + +regex.escape (`Hg issue 249 `_) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +regex.escape has an additional keyword parameter ``literal_spaces``. When True, spaces are not escaped. + +.. sourcecode:: python + + >>> regex.escape("foo bar!?", literal_spaces=False) + 'foo\\ bar!\\?' + >>> regex.escape("foo bar!?", literal_spaces=True) + 'foo bar!\\?' + +Repeated captures (`issue #7132 `_) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A match object has additional methods which return information on all the successful matches of a repeated group. These methods are: + +* ``matchobject.captures([group1, ...])`` + + * Returns a list of the strings matched in a group or groups. Compare with ``matchobject.group([group1, ...])``. + +* ``matchobject.starts([group])`` + + * Returns a list of the start positions. Compare with ``matchobject.start([group])``. + +* ``matchobject.ends([group])`` + + * Returns a list of the end positions. Compare with ``matchobject.end([group])``. + +* ``matchobject.spans([group])`` + + * Returns a list of the spans. Compare with ``matchobject.span([group])``. + +.. sourcecode:: python + + >>> m = regex.search(r"(\w{3})+", "123456789") + >>> m.group(1) + '789' + >>> m.captures(1) + ['123', '456', '789'] + >>> m.start(1) + 6 + >>> m.starts(1) + [0, 3, 6] + >>> m.end(1) + 9 + >>> m.ends(1) + [3, 6, 9] + >>> m.span(1) + (6, 9) + >>> m.spans(1) + [(0, 3), (3, 6), (6, 9)] + +Atomic grouping ``(?>...)`` (`issue #433030 `_) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If the following pattern subsequently fails, then the subpattern as a whole will fail. + +Possessive quantifiers +^^^^^^^^^^^^^^^^^^^^^^ + +``(?:...)?+`` ; ``(?:...)*+`` ; ``(?:...)++`` ; ``(?:...){min,max}+`` + +The subpattern is matched up to 'max' times. If the following pattern subsequently fails, then all the repeated subpatterns will fail as a whole. For example, ``(?:...)++`` is equivalent to ``(?>(?:...)+)``. + +Scoped flags (`issue #433028 `_) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``(?flags-flags:...)`` + +The flags will apply only to the subpattern. Flags can be turned on or off. + +Definition of 'word' character (`issue #1693050 `_) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The definition of a 'word' character has been expanded for Unicode. It conforms to the Unicode specification at ``http://www.unicode.org/reports/tr29/``. + +Variable-length lookbehind +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A lookbehind can match a variable-length string. + +Flags argument for regex.split, regex.sub and regex.subn (`issue #3482 `_) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``regex.split``, ``regex.sub`` and ``regex.subn`` support a 'flags' argument. + +Pos and endpos arguments for regex.sub and regex.subn +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``regex.sub`` and ``regex.subn`` support 'pos' and 'endpos' arguments. + +'Overlapped' argument for regex.findall and regex.finditer +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``regex.findall`` and ``regex.finditer`` support an 'overlapped' flag which permits overlapped matches. + +Splititer +^^^^^^^^^ + +``regex.splititer`` has been added. It's a generator equivalent of ``regex.split``. + +Subscripting match objects for groups +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A match object accepts access to the groups via subscripting and slicing: + +.. sourcecode:: python + + >>> m = regex.search(r"(?P.*?)(?P\d+)(?P.*)", "pqr123stu") + >>> print(m["before"]) + pqr + >>> print(len(m)) + 4 + >>> print(m[:]) + ('pqr123stu', 'pqr', '123', 'stu') + +Named groups +^^^^^^^^^^^^ + +Groups can be named with ``(?...)`` as well as the existing ``(?P...)``. + +Group references +^^^^^^^^^^^^^^^^ + +Groups can be referenced within a pattern with ``\g``. This also allows there to be more than 99 groups. + +Named characters ``\N{name}`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Named characters are supported. Note that only those known by Python's Unicode database will be recognised. + +Unicode codepoint properties, including scripts and blocks +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``\p{property=value}``; ``\P{property=value}``; ``\p{value}`` ; ``\P{value}`` + +Many Unicode properties are supported, including blocks and scripts. ``\p{property=value}`` or ``\p{property:value}`` matches a character whose property ``property`` has value ``value``. The inverse of ``\p{property=value}`` is ``\P{property=value}`` or ``\p{^property=value}``. + +If the short form ``\p{value}`` is used, the properties are checked in the order: ``General_Category``, ``Script``, ``Block``, binary property: + +* ``Latin``, the 'Latin' script (``Script=Latin``). + +* ``BasicLatin``, the 'BasicLatin' block (``Block=BasicLatin``). + +* ``Alphabetic``, the 'Alphabetic' binary property (``Alphabetic=Yes``). + +A short form starting with ``Is`` indicates a script or binary property: + +* ``IsLatin``, the 'Latin' script (``Script=Latin``). + +* ``IsAlphabetic``, the 'Alphabetic' binary property (``Alphabetic=Yes``). + +A short form starting with ``In`` indicates a block property: + +* ``InBasicLatin``, the 'BasicLatin' block (``Block=BasicLatin``). + +POSIX character classes +^^^^^^^^^^^^^^^^^^^^^^^ + +``[[:alpha:]]``; ``[[:^alpha:]]`` + +POSIX character classes are supported. These are normally treated as an alternative form of ``\p{...}``. + +The exceptions are ``alnum``, ``digit``, ``punct`` and ``xdigit``, whose definitions are different from those of Unicode. + +``[[:alnum:]]`` is equivalent to ``\p{posix_alnum}``. + +``[[:digit:]]`` is equivalent to ``\p{posix_digit}``. + +``[[:punct:]]`` is equivalent to ``\p{posix_punct}``. + +``[[:xdigit:]]`` is equivalent to ``\p{posix_xdigit}``. + +Search anchor ``\G`` +^^^^^^^^^^^^^^^^^^^^ + +A search anchor has been added. It matches at the position where each search started/continued and can be used for contiguous matches or in negative variable-length lookbehinds to limit how far back the lookbehind goes: + +.. sourcecode:: python + + >>> regex.findall(r"\w{2}", "abcd ef") + ['ab', 'cd', 'ef'] + >>> regex.findall(r"\G\w{2}", "abcd ef") + ['ab', 'cd'] + +* The search starts at position 0 and matches 'ab'. + +* The search continues at position 2 and matches 'cd'. + +* The search continues at position 4 and fails to match any letters. + +* The anchor stops the search start position from being advanced, so there are no more results. + +Reverse searching +^^^^^^^^^^^^^^^^^ + +Searches can also work backwards: + +.. sourcecode:: python + + >>> regex.findall(r".", "abc") + ['a', 'b', 'c'] + >>> regex.findall(r"(?r).", "abc") + ['c', 'b', 'a'] + +Note that the result of a reverse search is not necessarily the reverse of a forward search: + +.. sourcecode:: python + + >>> regex.findall(r"..", "abcde") + ['ab', 'cd'] + >>> regex.findall(r"(?r)..", "abcde") + ['de', 'bc'] + +Matching a single grapheme ``\X`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The grapheme matcher is supported. It conforms to the Unicode specification at ``http://www.unicode.org/reports/tr29/``. + +Branch reset ``(?|...|...)`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Group numbers will be reused across the alternatives, but groups with different names will have different group numbers. + +.. sourcecode:: python + + >>> regex.match(r"(?|(first)|(second))", "first").groups() + ('first',) + >>> regex.match(r"(?|(first)|(second))", "second").groups() + ('second',) + +Note that there is only one group. + +Default Unicode word boundary +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The ``WORD`` flag changes the definition of a 'word boundary' to that of a default Unicode word boundary. This applies to ``\b`` and ``\B``. + +Timeout +^^^^^^^ + +The matching methods and functions support timeouts. The timeout (in seconds) applies to the entire operation: + +.. sourcecode:: python + + >>> from time import sleep + >>> + >>> def fast_replace(m): + ... return 'X' + ... + >>> def slow_replace(m): + ... sleep(0.5) + ... return 'X' + ... + >>> regex.sub(r'[a-z]', fast_replace, 'abcde', timeout=2) + 'XXXXX' + >>> regex.sub(r'[a-z]', slow_replace, 'abcde', timeout=2) + Traceback (most recent call last): + File "", line 1, in + File "C:\Python310\lib\site-packages\regex\regex.py", line 278, in sub + return pat.sub(repl, string, count, pos, endpos, concurrent, timeout) + TimeoutError: regex timed out \ No newline at end of file