diagnostics: add support for "text art" diagrams

Existing text output in GCC has to be implemented by writing
sequentially to a pretty_printer instance.  This makes it
hard to implement some kinds of diagnostic output (see e.g.
diagnostic-show-locus.cc).

This patch adds more flexible ways of creating text output:
- a canvas class, which can be "painted" to via random-access (rather
that sequentially)
- a table class for 2D grid layout, supporting items that span
multiple rows/columns
- a widget class for organizing diagrams hierarchically.

The patch also expands GCC's diagnostics subsystem so that diagnostics
can have "text art" diagrams - think ASCII art, but potentially
including some Unicode characters, such as box-drawing chars.

The new code is in a new "gcc/text-art" subdirectory and "text_art"
namespace.

The patch adds a new "-fdiagnostics-text-art-charset=VAL" option, with
values:
- "none": don't emit diagrams (added to -fdiagnostics-plain-output)
- "ascii": use pure ASCII in diagrams
- "unicode": allow for conservative use of unicode drawing characters
(such as box-drawing characters).
- "emoji" (the default): as "unicode", but potentially allow for
conservative use of emoji in the output (such as U+26A0 WARNING SIGN).
I made it possible to disable emoji separately from unicode as I believe
there's a generation gap in acceptance of these characters (some older
programmers have a visceral reaction against them, whereas younger
programmers may have no problem with them).

Diagrams are emitted to stderr by default.  With SARIF output they are
captured as a location in "relatedLocations", with the diagram as a
code block in Markdown within a "markdown" property of a message.

This patch doesn't add any such diagram usage to GCC, saving that for
followups, apart from adding a plugin to the test suite to exercise the
functionality.

contrib/ChangeLog:
	* unicode/gen-box-drawing-chars.py: New file.
	* unicode/gen-combining-chars.py: New file.
	* unicode/gen-printable-chars.py: New file.

gcc/ChangeLog:
	* Makefile.in (OBJS-libcommon): Add text-art/box-drawing.o,
	text-art/canvas.o, text-art/ruler.o, text-art/selftests.o,
	text-art/style.o, text-art/styled-string.o, text-art/table.o,
	text-art/theme.o, and text-art/widget.o.
	* color-macros.h (COLOR_FG_BRIGHT_BLACK): New.
	(COLOR_FG_BRIGHT_RED): New.
	(COLOR_FG_BRIGHT_GREEN): New.
	(COLOR_FG_BRIGHT_YELLOW): New.
	(COLOR_FG_BRIGHT_BLUE): New.
	(COLOR_FG_BRIGHT_MAGENTA): New.
	(COLOR_FG_BRIGHT_CYAN): New.
	(COLOR_FG_BRIGHT_WHITE): New.
	(COLOR_BG_BRIGHT_BLACK): New.
	(COLOR_BG_BRIGHT_RED): New.
	(COLOR_BG_BRIGHT_GREEN): New.
	(COLOR_BG_BRIGHT_YELLOW): New.
	(COLOR_BG_BRIGHT_BLUE): New.
	(COLOR_BG_BRIGHT_MAGENTA): New.
	(COLOR_BG_BRIGHT_CYAN): New.
	(COLOR_BG_BRIGHT_WHITE): New.
	* common.opt (fdiagnostics-text-art-charset=): New option.
	(diagnostic-text-art.h): New SourceInclude.
	(diagnostic_text_art_charset) New Enum and EnumValues.
	* configure: Regenerate.
	* configure.ac (gccdepdir): Add text-art to loop.
	* diagnostic-diagram.h: New file.
	* diagnostic-format-json.cc (json_emit_diagram): New.
	(diagnostic_output_format_init_json): Wire it up to
	context->m_diagrams.m_emission_cb.
	* diagnostic-format-sarif.cc: Include "diagnostic-diagram.h" and
	"text-art/canvas.h".
	(sarif_result::on_nested_diagnostic): Move code to...
	(sarif_result::add_related_location): ...this new function.
	(sarif_result::on_diagram): New.
	(sarif_builder::emit_diagram): New.
	(sarif_builder::make_message_object_for_diagram): New.
	(sarif_emit_diagram): New.
	(diagnostic_output_format_init_sarif): Set
	context->m_diagrams.m_emission_cb to sarif_emit_diagram.
	* diagnostic-text-art.h: New file.
	* diagnostic.cc: Include "diagnostic-text-art.h",
	"diagnostic-diagram.h", and "text-art/theme.h".
	(diagnostic_initialize): Initialize context->m_diagrams and
	call diagnostics_text_art_charset_init.
	(diagnostic_finish): Clean up context->m_diagrams.m_theme.
	(diagnostic_emit_diagram): New.
	(diagnostics_text_art_charset_init): New.
	* diagnostic.h (text_art::theme): New forward decl.
	(class diagnostic_diagram): Likewise.
	(diagnostic_context::m_diagrams): New field.
	(diagnostic_emit_diagram): New decl.
	* doc/invoke.texi (Diagnostic Message Formatting Options): Add
	-fdiagnostics-text-art-charset=.
	(-fdiagnostics-plain-output): Add
	-fdiagnostics-text-art-charset=none.
	* gcc.cc: Include "diagnostic-text-art.h".
	(driver_handle_option): Handle OPT_fdiagnostics_text_art_charset_.
	* opts-common.cc (decode_cmdline_options_to_array): Add
	"-fdiagnostics-text-art-charset=none" to expanded_args for
	-fdiagnostics-plain-output.
	* opts.cc: Include "diagnostic-text-art.h".
	(common_handle_option): Handle OPT_fdiagnostics_text_art_charset_.
	* pretty-print.cc (pp_unicode_character): New.
	* pretty-print.h (pp_unicode_character): New decl.
	* selftest-run-tests.cc: Include "text-art/selftests.h".
	(selftest::run_tests): Call text_art_tests.
	* text-art/box-drawing-chars.inc: New file, generated by
	contrib/unicode/gen-box-drawing-chars.py.
	* text-art/box-drawing.cc: New file.
	* text-art/box-drawing.h: New file.
	* text-art/canvas.cc: New file.
	* text-art/canvas.h: New file.
	* text-art/ruler.cc: New file.
	* text-art/ruler.h: New file.
	* text-art/selftests.cc: New file.
	* text-art/selftests.h: New file.
	* text-art/style.cc: New file.
	* text-art/styled-string.cc: New file.
	* text-art/table.cc: New file.
	* text-art/table.h: New file.
	* text-art/theme.cc: New file.
	* text-art/theme.h: New file.
	* text-art/types.h: New file.
	* text-art/widget.cc: New file.
	* text-art/widget.h: New file.

gcc/testsuite/ChangeLog:
	* gcc.dg/plugin/diagnostic-test-text-art-ascii-bw.c: New test.
	* gcc.dg/plugin/diagnostic-test-text-art-ascii-color.c: New test.
	* gcc.dg/plugin/diagnostic-test-text-art-none.c: New test.
	* gcc.dg/plugin/diagnostic-test-text-art-unicode-bw.c: New test.
	* gcc.dg/plugin/diagnostic-test-text-art-unicode-color.c: New test.
	* gcc.dg/plugin/diagnostic_plugin_test_text_art.c: New test plugin.
	* gcc.dg/plugin/plugin.exp (plugin_test_list): Add them.

libcpp/ChangeLog:
	* charset.cc (get_cppchar_property): New function template, based
	on...
	(cpp_wcwidth): ...this function.  Rework to use the above.
	Include "combining-chars.inc".
	(cpp_is_combining_char): New function
	Include "printable-chars.inc".
	(cpp_is_printable_char): New function
	* combining-chars.inc: New file, generated by
	contrib/unicode/gen-combining-chars.py.
	* include/cpplib.h (cpp_is_combining_char): New function decl.
	(cpp_is_printable_char): New function decl.
	* printable-chars.inc: New file, generated by
	contrib/unicode/gen-printable-chars.py.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
This commit is contained in:
David Malcolm
2023-06-21 21:49:00 -04:00
parent 985d6480fe
commit 4f01ae3761
50 changed files with 7764 additions and 37 deletions

View File

@@ -3154,6 +3154,40 @@ cpp_display_column_to_byte_column (const char *data, int data_length,
return dw.bytes_processed () + MAX (0, display_col - avail_display);
}
template <typename PropertyType>
PropertyType
get_cppchar_property (cppchar_t c,
const cppchar_t *range_ends,
const PropertyType *range_values,
size_t num_ranges,
PropertyType default_value)
{
if (__builtin_expect (c <= range_ends[0], true))
return range_values[0];
/* Binary search the tables. */
int begin = 1;
static const int end = num_ranges;
int len = end - begin;
do
{
int half = len/2;
int middle = begin + half;
if (c > range_ends[middle])
{
begin = middle + 1;
len -= half + 1;
}
else
len = half;
} while (len);
if (__builtin_expect (begin != end, true))
return range_values[begin];
return default_value;
}
/* Our own version of wcwidth(). We don't use the actual wcwidth() in glibc,
because that will inspect the user's locale, and in particular in an ASCII
locale, it will not return anything useful for extended characters. But GCC
@@ -3167,30 +3201,43 @@ cpp_display_column_to_byte_column (const char *data, int data_length,
diagnostics, they are sufficient. */
#include "generated_cpp_wcwidth.h"
int cpp_wcwidth (cppchar_t c)
int
cpp_wcwidth (cppchar_t c)
{
if (__builtin_expect (c <= wcwidth_range_ends[0], true))
return wcwidth_widths[0];
/* Binary search the tables. */
int begin = 1;
static const int end
= sizeof wcwidth_range_ends / sizeof (*wcwidth_range_ends);
int len = end - begin;
do
{
int half = len/2;
int middle = begin + half;
if (c > wcwidth_range_ends[middle])
{
begin = middle + 1;
len -= half + 1;
}
else
len = half;
} while (len);
if (__builtin_expect (begin != end, true))
return wcwidth_widths[begin];
return 1;
const size_t num_ranges
= sizeof wcwidth_range_ends / sizeof (*wcwidth_range_ends);
return get_cppchar_property<unsigned char > (c,
&wcwidth_range_ends[0],
&wcwidth_widths[0],
num_ranges,
1);
}
#include "combining-chars.inc"
bool
cpp_is_combining_char (cppchar_t c)
{
const size_t num_ranges
= sizeof combining_range_ends / sizeof (*combining_range_ends);
return get_cppchar_property<bool> (c,
&combining_range_ends[0],
&is_combining[0],
num_ranges,
false);
}
#include "printable-chars.inc"
bool
cpp_is_printable_char (cppchar_t c)
{
const size_t num_ranges
= sizeof printable_range_ends / sizeof (*printable_range_ends);
return get_cppchar_property<bool> (c,
&printable_range_ends[0],
&is_printable[0],
num_ranges,
false);
}

View File

@@ -0,0 +1,68 @@
/* Generated by contrib/unicode/gen-combining-chars.py
using version 12.1.0 of the Unicode standard. */
static const cppchar_t combining_range_ends[] = {
0x2ff, 0x34e, 0x34f, 0x36f, 0x482, 0x487, 0x590, 0x5bd,
0x5be, 0x5bf, 0x5c0, 0x5c2, 0x5c3, 0x5c5, 0x5c6, 0x5c7,
0x60f, 0x61a, 0x64a, 0x65f, 0x66f, 0x670, 0x6d5, 0x6dc,
0x6de, 0x6e4, 0x6e6, 0x6e8, 0x6e9, 0x6ed, 0x710, 0x711,
0x72f, 0x74a, 0x7ea, 0x7f3, 0x7fc, 0x7fd, 0x815, 0x819,
0x81a, 0x823, 0x824, 0x827, 0x828, 0x82d, 0x858, 0x85b,
0x8d2, 0x8e1, 0x8e2, 0x8ff, 0x93b, 0x93c, 0x94c, 0x94d,
0x950, 0x954, 0x9bb, 0x9bc, 0x9cc, 0x9cd, 0x9fd, 0x9fe,
0xa3b, 0xa3c, 0xa4c, 0xa4d, 0xabb, 0xabc, 0xacc, 0xacd,
0xb3b, 0xb3c, 0xb4c, 0xb4d, 0xbcc, 0xbcd, 0xc4c, 0xc4d,
0xc54, 0xc56, 0xcbb, 0xcbc, 0xccc, 0xccd, 0xd3a, 0xd3c,
0xd4c, 0xd4d, 0xdc9, 0xdca, 0xe37, 0xe3a, 0xe47, 0xe4b,
0xeb7, 0xeba, 0xec7, 0xecb, 0xf17, 0xf19, 0xf34, 0xf35,
0xf36, 0xf37, 0xf38, 0xf39, 0xf70, 0xf72, 0xf73, 0xf74,
0xf79, 0xf7d, 0xf7f, 0xf80, 0xf81, 0xf84, 0xf85, 0xf87,
0xfc5, 0xfc6, 0x1036, 0x1037, 0x1038, 0x103a, 0x108c, 0x108d,
0x135c, 0x135f, 0x1713, 0x1714, 0x1733, 0x1734, 0x17d1, 0x17d2,
0x17dc, 0x17dd, 0x18a8, 0x18a9, 0x1938, 0x193b, 0x1a16, 0x1a18,
0x1a5f, 0x1a60, 0x1a74, 0x1a7c, 0x1a7e, 0x1a7f, 0x1aaf, 0x1abd,
0x1b33, 0x1b34, 0x1b43, 0x1b44, 0x1b6a, 0x1b73, 0x1ba9, 0x1bab,
0x1be5, 0x1be6, 0x1bf1, 0x1bf3, 0x1c36, 0x1c37, 0x1ccf, 0x1cd2,
0x1cd3, 0x1ce0, 0x1ce1, 0x1ce8, 0x1cec, 0x1ced, 0x1cf3, 0x1cf4,
0x1cf7, 0x1cf9, 0x1dbf, 0x1df9, 0x1dfa, 0x1dff, 0x20cf, 0x20dc,
0x20e0, 0x20e1, 0x20e4, 0x20f0, 0x2cee, 0x2cf1, 0x2d7e, 0x2d7f,
0x2ddf, 0x2dff, 0x3029, 0x302f, 0x3098, 0x309a, 0xa66e, 0xa66f,
0xa673, 0xa67d, 0xa69d, 0xa69f, 0xa6ef, 0xa6f1, 0xa805, 0xa806,
0xa8c3, 0xa8c4, 0xa8df, 0xa8f1, 0xa92a, 0xa92d, 0xa952, 0xa953,
0xa9b2, 0xa9b3, 0xa9bf, 0xa9c0, 0xaaaf, 0xaab0, 0xaab1, 0xaab4,
0xaab6, 0xaab8, 0xaabd, 0xaabf, 0xaac0, 0xaac1, 0xaaf5, 0xaaf6,
0xabec, 0xabed, 0xfb1d, 0xfb1e, 0xfe1f, 0xfe2f, 0x101fc, 0x101fd,
0x102df, 0x102e0, 0x10375, 0x1037a, 0x10a0c, 0x10a0d, 0x10a0e, 0x10a0f,
0x10a37, 0x10a3a, 0x10a3e, 0x10a3f, 0x10ae4, 0x10ae6, 0x10d23, 0x10d27,
0x10f45, 0x10f50, 0x11045, 0x11046, 0x1107e, 0x1107f, 0x110b8, 0x110ba,
0x110ff, 0x11102, 0x11132, 0x11134, 0x11172, 0x11173, 0x111bf, 0x111c0,
0x111c9, 0x111ca, 0x11234, 0x11236, 0x112e8, 0x112ea, 0x1133a, 0x1133c,
0x1134c, 0x1134d, 0x11365, 0x1136c, 0x1136f, 0x11374, 0x11441, 0x11442,
0x11445, 0x11446, 0x1145d, 0x1145e, 0x114c1, 0x114c3, 0x115be, 0x115c0,
0x1163e, 0x1163f, 0x116b5, 0x116b7, 0x1172a, 0x1172b, 0x11838, 0x1183a,
0x119df, 0x119e0, 0x11a33, 0x11a34, 0x11a46, 0x11a47, 0x11a98, 0x11a99,
0x11c3e, 0x11c3f, 0x11d41, 0x11d42, 0x11d43, 0x11d45, 0x11d96, 0x11d97,
0x16aef, 0x16af4, 0x16b2f, 0x16b36, 0x1bc9d, 0x1bc9e, 0x1d164, 0x1d169,
0x1d16c, 0x1d172, 0x1d17a, 0x1d182, 0x1d184, 0x1d18b, 0x1d1a9, 0x1d1ad,
0x1d241, 0x1d244, 0x1dfff, 0x1e006, 0x1e007, 0x1e018, 0x1e01a, 0x1e021,
0x1e022, 0x1e024, 0x1e025, 0x1e02a, 0x1e12f, 0x1e136, 0x1e2eb, 0x1e2ef,
0x1e8cf, 0x1e8d6, 0x1e943, 0x1e94a, 0x10fffe,
};
static const bool is_combining[] = {
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, 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, 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, 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, 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, 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, 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, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
};

View File

@@ -1602,4 +1602,7 @@ bool cpp_input_conversion_is_trivial (const char *input_charset);
int cpp_check_utf8_bom (const char *data, size_t data_length);
bool cpp_valid_utf8_p (const char *data, size_t num_bytes);
bool cpp_is_combining_char (cppchar_t c);
bool cpp_is_printable_char (cppchar_t c);
#endif /* ! LIBCPP_CPPLIB_H */

231
libcpp/printable-chars.inc Normal file
View File

@@ -0,0 +1,231 @@
/* Generated by contrib/unicode/gen-printable-chars.py
using version 12.1.0 of the Unicode standard. */
static const cppchar_t printable_range_ends[] = {
0x1f, 0x7e, 0x9f, 0xac, 0xad, 0x377, 0x379, 0x37f,
0x383, 0x38a, 0x38b, 0x38c, 0x38d, 0x3a1, 0x3a2, 0x52f,
0x530, 0x556, 0x558, 0x58a, 0x58c, 0x58f, 0x590, 0x5c7,
0x5cf, 0x5ea, 0x5ee, 0x5f4, 0x605, 0x61b, 0x61d, 0x6dc,
0x6dd, 0x70d, 0x70f, 0x74a, 0x74c, 0x7b1, 0x7bf, 0x7fa,
0x7fc, 0x82d, 0x82f, 0x83e, 0x83f, 0x85b, 0x85d, 0x85e,
0x85f, 0x86a, 0x89f, 0x8b4, 0x8b5, 0x8bd, 0x8d2, 0x8e1,
0x8e2, 0x983, 0x984, 0x98c, 0x98e, 0x990, 0x992, 0x9a8,
0x9a9, 0x9b0, 0x9b1, 0x9b2, 0x9b5, 0x9b9, 0x9bb, 0x9c4,
0x9c6, 0x9c8, 0x9ca, 0x9ce, 0x9d6, 0x9d7, 0x9db, 0x9dd,
0x9de, 0x9e3, 0x9e5, 0x9fe, 0xa00, 0xa03, 0xa04, 0xa0a,
0xa0e, 0xa10, 0xa12, 0xa28, 0xa29, 0xa30, 0xa31, 0xa33,
0xa34, 0xa36, 0xa37, 0xa39, 0xa3b, 0xa3c, 0xa3d, 0xa42,
0xa46, 0xa48, 0xa4a, 0xa4d, 0xa50, 0xa51, 0xa58, 0xa5c,
0xa5d, 0xa5e, 0xa65, 0xa76, 0xa80, 0xa83, 0xa84, 0xa8d,
0xa8e, 0xa91, 0xa92, 0xaa8, 0xaa9, 0xab0, 0xab1, 0xab3,
0xab4, 0xab9, 0xabb, 0xac5, 0xac6, 0xac9, 0xaca, 0xacd,
0xacf, 0xad0, 0xadf, 0xae3, 0xae5, 0xaf1, 0xaf8, 0xaff,
0xb00, 0xb03, 0xb04, 0xb0c, 0xb0e, 0xb10, 0xb12, 0xb28,
0xb29, 0xb30, 0xb31, 0xb33, 0xb34, 0xb39, 0xb3b, 0xb44,
0xb46, 0xb48, 0xb4a, 0xb4d, 0xb55, 0xb57, 0xb5b, 0xb5d,
0xb5e, 0xb63, 0xb65, 0xb77, 0xb81, 0xb83, 0xb84, 0xb8a,
0xb8d, 0xb90, 0xb91, 0xb95, 0xb98, 0xb9a, 0xb9b, 0xb9c,
0xb9d, 0xb9f, 0xba2, 0xba4, 0xba7, 0xbaa, 0xbad, 0xbb9,
0xbbd, 0xbc2, 0xbc5, 0xbc8, 0xbc9, 0xbcd, 0xbcf, 0xbd0,
0xbd6, 0xbd7, 0xbe5, 0xbfa, 0xbff, 0xc0c, 0xc0d, 0xc10,
0xc11, 0xc28, 0xc29, 0xc39, 0xc3c, 0xc44, 0xc45, 0xc48,
0xc49, 0xc4d, 0xc54, 0xc56, 0xc57, 0xc5a, 0xc5f, 0xc63,
0xc65, 0xc6f, 0xc76, 0xc8c, 0xc8d, 0xc90, 0xc91, 0xca8,
0xca9, 0xcb3, 0xcb4, 0xcb9, 0xcbb, 0xcc4, 0xcc5, 0xcc8,
0xcc9, 0xccd, 0xcd4, 0xcd6, 0xcdd, 0xcde, 0xcdf, 0xce3,
0xce5, 0xcef, 0xcf0, 0xcf2, 0xcff, 0xd03, 0xd04, 0xd0c,
0xd0d, 0xd10, 0xd11, 0xd44, 0xd45, 0xd48, 0xd49, 0xd4f,
0xd53, 0xd63, 0xd65, 0xd7f, 0xd81, 0xd83, 0xd84, 0xd96,
0xd99, 0xdb1, 0xdb2, 0xdbb, 0xdbc, 0xdbd, 0xdbf, 0xdc6,
0xdc9, 0xdca, 0xdce, 0xdd4, 0xdd5, 0xdd6, 0xdd7, 0xddf,
0xde5, 0xdef, 0xdf1, 0xdf4, 0xe00, 0xe3a, 0xe3e, 0xe5b,
0xe80, 0xe82, 0xe83, 0xe84, 0xe85, 0xe8a, 0xe8b, 0xea3,
0xea4, 0xea5, 0xea6, 0xebd, 0xebf, 0xec4, 0xec5, 0xec6,
0xec7, 0xecd, 0xecf, 0xed9, 0xedb, 0xedf, 0xeff, 0xf47,
0xf48, 0xf6c, 0xf70, 0xf97, 0xf98, 0xfbc, 0xfbd, 0xfcc,
0xfcd, 0xfda, 0xfff, 0x10c5, 0x10c6, 0x10c7, 0x10cc, 0x10cd,
0x10cf, 0x1248, 0x1249, 0x124d, 0x124f, 0x1256, 0x1257, 0x1258,
0x1259, 0x125d, 0x125f, 0x1288, 0x1289, 0x128d, 0x128f, 0x12b0,
0x12b1, 0x12b5, 0x12b7, 0x12be, 0x12bf, 0x12c0, 0x12c1, 0x12c5,
0x12c7, 0x12d6, 0x12d7, 0x1310, 0x1311, 0x1315, 0x1317, 0x135a,
0x135c, 0x137c, 0x137f, 0x1399, 0x139f, 0x13f5, 0x13f7, 0x13fd,
0x13ff, 0x169c, 0x169f, 0x16f8, 0x16ff, 0x170c, 0x170d, 0x1714,
0x171f, 0x1736, 0x173f, 0x1753, 0x175f, 0x176c, 0x176d, 0x1770,
0x1771, 0x1773, 0x177f, 0x17dd, 0x17df, 0x17e9, 0x17ef, 0x17f9,
0x17ff, 0x180d, 0x180f, 0x1819, 0x181f, 0x1878, 0x187f, 0x18aa,
0x18af, 0x18f5, 0x18ff, 0x191e, 0x191f, 0x192b, 0x192f, 0x193b,
0x193f, 0x1940, 0x1943, 0x196d, 0x196f, 0x1974, 0x197f, 0x19ab,
0x19af, 0x19c9, 0x19cf, 0x19da, 0x19dd, 0x1a1b, 0x1a1d, 0x1a5e,
0x1a5f, 0x1a7c, 0x1a7e, 0x1a89, 0x1a8f, 0x1a99, 0x1a9f, 0x1aad,
0x1aaf, 0x1abe, 0x1aff, 0x1b4b, 0x1b4f, 0x1b7c, 0x1b7f, 0x1bf3,
0x1bfb, 0x1c37, 0x1c3a, 0x1c49, 0x1c4c, 0x1c88, 0x1c8f, 0x1cba,
0x1cbc, 0x1cc7, 0x1ccf, 0x1cfa, 0x1cff, 0x1df9, 0x1dfa, 0x1f15,
0x1f17, 0x1f1d, 0x1f1f, 0x1f45, 0x1f47, 0x1f4d, 0x1f4f, 0x1f57,
0x1f58, 0x1f59, 0x1f5a, 0x1f5b, 0x1f5c, 0x1f5d, 0x1f5e, 0x1f7d,
0x1f7f, 0x1fb4, 0x1fb5, 0x1fc4, 0x1fc5, 0x1fd3, 0x1fd5, 0x1fdb,
0x1fdc, 0x1fef, 0x1ff1, 0x1ff4, 0x1ff5, 0x1ffe, 0x1fff, 0x200a,
0x200f, 0x2029, 0x202e, 0x205f, 0x206f, 0x2071, 0x2073, 0x208e,
0x208f, 0x209c, 0x209f, 0x20bf, 0x20cf, 0x20f0, 0x20ff, 0x218b,
0x218f, 0x2426, 0x243f, 0x244a, 0x245f, 0x2b73, 0x2b75, 0x2b95,
0x2b97, 0x2c2e, 0x2c2f, 0x2c5e, 0x2c5f, 0x2cf3, 0x2cf8, 0x2d25,
0x2d26, 0x2d27, 0x2d2c, 0x2d2d, 0x2d2f, 0x2d67, 0x2d6e, 0x2d70,
0x2d7e, 0x2d96, 0x2d9f, 0x2da6, 0x2da7, 0x2dae, 0x2daf, 0x2db6,
0x2db7, 0x2dbe, 0x2dbf, 0x2dc6, 0x2dc7, 0x2dce, 0x2dcf, 0x2dd6,
0x2dd7, 0x2dde, 0x2ddf, 0x2e4f, 0x2e7f, 0x2e99, 0x2e9a, 0x2ef3,
0x2eff, 0x2fd5, 0x2fef, 0x2ffb, 0x2fff, 0x303f, 0x3040, 0x3096,
0x3098, 0x30ff, 0x3104, 0x312f, 0x3130, 0x318e, 0x318f, 0x31ba,
0x31bf, 0x31e3, 0x31ef, 0x321e, 0x321f, 0x4db5, 0x4dbf, 0x9fef,
0x9fff, 0xa48c, 0xa48f, 0xa4c6, 0xa4cf, 0xa62b, 0xa63f, 0xa6f7,
0xa6ff, 0xa7bf, 0xa7c1, 0xa7c6, 0xa7f6, 0xa82b, 0xa82f, 0xa839,
0xa83f, 0xa877, 0xa87f, 0xa8c5, 0xa8cd, 0xa8d9, 0xa8df, 0xa953,
0xa95e, 0xa97c, 0xa97f, 0xa9cd, 0xa9ce, 0xa9d9, 0xa9dd, 0xa9fe,
0xa9ff, 0xaa36, 0xaa3f, 0xaa4d, 0xaa4f, 0xaa59, 0xaa5b, 0xaac2,
0xaada, 0xaaf6, 0xab00, 0xab06, 0xab08, 0xab0e, 0xab10, 0xab16,
0xab1f, 0xab26, 0xab27, 0xab2e, 0xab2f, 0xab67, 0xab6f, 0xabed,
0xabef, 0xabf9, 0xabff, 0xd7a3, 0xd7af, 0xd7c6, 0xd7ca, 0xd7fb,
0xf8ff, 0xfa6d, 0xfa6f, 0xfad9, 0xfaff, 0xfb06, 0xfb12, 0xfb17,
0xfb1c, 0xfb36, 0xfb37, 0xfb3c, 0xfb3d, 0xfb3e, 0xfb3f, 0xfb41,
0xfb42, 0xfb44, 0xfb45, 0xfbc1, 0xfbd2, 0xfd3f, 0xfd4f, 0xfd8f,
0xfd91, 0xfdc7, 0xfdef, 0xfdfd, 0xfdff, 0xfe19, 0xfe1f, 0xfe52,
0xfe53, 0xfe66, 0xfe67, 0xfe6b, 0xfe6f, 0xfe74, 0xfe75, 0xfefc,
0xff00, 0xffbe, 0xffc1, 0xffc7, 0xffc9, 0xffcf, 0xffd1, 0xffd7,
0xffd9, 0xffdc, 0xffdf, 0xffe6, 0xffe7, 0xffee, 0xfffb, 0xfffd,
0xffff, 0x1000b, 0x1000c, 0x10026, 0x10027, 0x1003a, 0x1003b, 0x1003d,
0x1003e, 0x1004d, 0x1004f, 0x1005d, 0x1007f, 0x100fa, 0x100ff, 0x10102,
0x10106, 0x10133, 0x10136, 0x1018e, 0x1018f, 0x1019b, 0x1019f, 0x101a0,
0x101cf, 0x101fd, 0x1027f, 0x1029c, 0x1029f, 0x102d0, 0x102df, 0x102fb,
0x102ff, 0x10323, 0x1032c, 0x1034a, 0x1034f, 0x1037a, 0x1037f, 0x1039d,
0x1039e, 0x103c3, 0x103c7, 0x103d5, 0x103ff, 0x1049d, 0x1049f, 0x104a9,
0x104af, 0x104d3, 0x104d7, 0x104fb, 0x104ff, 0x10527, 0x1052f, 0x10563,
0x1056e, 0x1056f, 0x105ff, 0x10736, 0x1073f, 0x10755, 0x1075f, 0x10767,
0x107ff, 0x10805, 0x10807, 0x10808, 0x10809, 0x10835, 0x10836, 0x10838,
0x1083b, 0x1083c, 0x1083e, 0x10855, 0x10856, 0x1089e, 0x108a6, 0x108af,
0x108df, 0x108f2, 0x108f3, 0x108f5, 0x108fa, 0x1091b, 0x1091e, 0x10939,
0x1093e, 0x1093f, 0x1097f, 0x109b7, 0x109bb, 0x109cf, 0x109d1, 0x10a03,
0x10a04, 0x10a06, 0x10a0b, 0x10a13, 0x10a14, 0x10a17, 0x10a18, 0x10a35,
0x10a37, 0x10a3a, 0x10a3e, 0x10a48, 0x10a4f, 0x10a58, 0x10a5f, 0x10a9f,
0x10abf, 0x10ae6, 0x10aea, 0x10af6, 0x10aff, 0x10b35, 0x10b38, 0x10b55,
0x10b57, 0x10b72, 0x10b77, 0x10b91, 0x10b98, 0x10b9c, 0x10ba8, 0x10baf,
0x10bff, 0x10c48, 0x10c7f, 0x10cb2, 0x10cbf, 0x10cf2, 0x10cf9, 0x10d27,
0x10d2f, 0x10d39, 0x10e5f, 0x10e7e, 0x10eff, 0x10f27, 0x10f2f, 0x10f59,
0x10fdf, 0x10ff6, 0x10fff, 0x1104d, 0x11051, 0x1106f, 0x1107e, 0x110bc,
0x110bd, 0x110c1, 0x110cf, 0x110e8, 0x110ef, 0x110f9, 0x110ff, 0x11134,
0x11135, 0x11146, 0x1114f, 0x11176, 0x1117f, 0x111cd, 0x111cf, 0x111df,
0x111e0, 0x111f4, 0x111ff, 0x11211, 0x11212, 0x1123e, 0x1127f, 0x11286,
0x11287, 0x11288, 0x11289, 0x1128d, 0x1128e, 0x1129d, 0x1129e, 0x112a9,
0x112af, 0x112ea, 0x112ef, 0x112f9, 0x112ff, 0x11303, 0x11304, 0x1130c,
0x1130e, 0x11310, 0x11312, 0x11328, 0x11329, 0x11330, 0x11331, 0x11333,
0x11334, 0x11339, 0x1133a, 0x11344, 0x11346, 0x11348, 0x1134a, 0x1134d,
0x1134f, 0x11350, 0x11356, 0x11357, 0x1135c, 0x11363, 0x11365, 0x1136c,
0x1136f, 0x11374, 0x113ff, 0x11459, 0x1145a, 0x1145b, 0x1145c, 0x1145f,
0x1147f, 0x114c7, 0x114cf, 0x114d9, 0x1157f, 0x115b5, 0x115b7, 0x115dd,
0x115ff, 0x11644, 0x1164f, 0x11659, 0x1165f, 0x1166c, 0x1167f, 0x116b8,
0x116bf, 0x116c9, 0x116ff, 0x1171a, 0x1171c, 0x1172b, 0x1172f, 0x1173f,
0x117ff, 0x1183b, 0x1189f, 0x118f2, 0x118fe, 0x118ff, 0x1199f, 0x119a7,
0x119a9, 0x119d7, 0x119d9, 0x119e4, 0x119ff, 0x11a47, 0x11a4f, 0x11aa2,
0x11abf, 0x11af8, 0x11bff, 0x11c08, 0x11c09, 0x11c36, 0x11c37, 0x11c45,
0x11c4f, 0x11c6c, 0x11c6f, 0x11c8f, 0x11c91, 0x11ca7, 0x11ca8, 0x11cb6,
0x11cff, 0x11d06, 0x11d07, 0x11d09, 0x11d0a, 0x11d36, 0x11d39, 0x11d3a,
0x11d3b, 0x11d3d, 0x11d3e, 0x11d47, 0x11d4f, 0x11d59, 0x11d5f, 0x11d65,
0x11d66, 0x11d68, 0x11d69, 0x11d8e, 0x11d8f, 0x11d91, 0x11d92, 0x11d98,
0x11d9f, 0x11da9, 0x11edf, 0x11ef8, 0x11fbf, 0x11ff1, 0x11ffe, 0x12399,
0x123ff, 0x1246e, 0x1246f, 0x12474, 0x1247f, 0x12543, 0x12fff, 0x1342e,
0x143ff, 0x14646, 0x167ff, 0x16a38, 0x16a3f, 0x16a5e, 0x16a5f, 0x16a69,
0x16a6d, 0x16a6f, 0x16acf, 0x16aed, 0x16aef, 0x16af5, 0x16aff, 0x16b45,
0x16b4f, 0x16b59, 0x16b5a, 0x16b61, 0x16b62, 0x16b77, 0x16b7c, 0x16b8f,
0x16e3f, 0x16e9a, 0x16eff, 0x16f4a, 0x16f4e, 0x16f87, 0x16f8e, 0x16f9f,
0x16fdf, 0x16fe3, 0x16fff, 0x187f7, 0x187ff, 0x18af2, 0x1afff, 0x1b11e,
0x1b14f, 0x1b152, 0x1b163, 0x1b167, 0x1b16f, 0x1b2fb, 0x1bbff, 0x1bc6a,
0x1bc6f, 0x1bc7c, 0x1bc7f, 0x1bc88, 0x1bc8f, 0x1bc99, 0x1bc9b, 0x1bc9f,
0x1cfff, 0x1d0f5, 0x1d0ff, 0x1d126, 0x1d128, 0x1d172, 0x1d17a, 0x1d1e8,
0x1d1ff, 0x1d245, 0x1d2df, 0x1d2f3, 0x1d2ff, 0x1d356, 0x1d35f, 0x1d378,
0x1d3ff, 0x1d454, 0x1d455, 0x1d49c, 0x1d49d, 0x1d49f, 0x1d4a1, 0x1d4a2,
0x1d4a4, 0x1d4a6, 0x1d4a8, 0x1d4ac, 0x1d4ad, 0x1d4b9, 0x1d4ba, 0x1d4bb,
0x1d4bc, 0x1d4c3, 0x1d4c4, 0x1d505, 0x1d506, 0x1d50a, 0x1d50c, 0x1d514,
0x1d515, 0x1d51c, 0x1d51d, 0x1d539, 0x1d53a, 0x1d53e, 0x1d53f, 0x1d544,
0x1d545, 0x1d546, 0x1d549, 0x1d550, 0x1d551, 0x1d6a5, 0x1d6a7, 0x1d7cb,
0x1d7cd, 0x1da8b, 0x1da9a, 0x1da9f, 0x1daa0, 0x1daaf, 0x1dfff, 0x1e006,
0x1e007, 0x1e018, 0x1e01a, 0x1e021, 0x1e022, 0x1e024, 0x1e025, 0x1e02a,
0x1e0ff, 0x1e12c, 0x1e12f, 0x1e13d, 0x1e13f, 0x1e149, 0x1e14d, 0x1e14f,
0x1e2bf, 0x1e2f9, 0x1e2fe, 0x1e2ff, 0x1e7ff, 0x1e8c4, 0x1e8c6, 0x1e8d6,
0x1e8ff, 0x1e94b, 0x1e94f, 0x1e959, 0x1e95d, 0x1e95f, 0x1ec70, 0x1ecb4,
0x1ed00, 0x1ed3d, 0x1edff, 0x1ee03, 0x1ee04, 0x1ee1f, 0x1ee20, 0x1ee22,
0x1ee23, 0x1ee24, 0x1ee26, 0x1ee27, 0x1ee28, 0x1ee32, 0x1ee33, 0x1ee37,
0x1ee38, 0x1ee39, 0x1ee3a, 0x1ee3b, 0x1ee41, 0x1ee42, 0x1ee46, 0x1ee47,
0x1ee48, 0x1ee49, 0x1ee4a, 0x1ee4b, 0x1ee4c, 0x1ee4f, 0x1ee50, 0x1ee52,
0x1ee53, 0x1ee54, 0x1ee56, 0x1ee57, 0x1ee58, 0x1ee59, 0x1ee5a, 0x1ee5b,
0x1ee5c, 0x1ee5d, 0x1ee5e, 0x1ee5f, 0x1ee60, 0x1ee62, 0x1ee63, 0x1ee64,
0x1ee66, 0x1ee6a, 0x1ee6b, 0x1ee72, 0x1ee73, 0x1ee77, 0x1ee78, 0x1ee7c,
0x1ee7d, 0x1ee7e, 0x1ee7f, 0x1ee89, 0x1ee8a, 0x1ee9b, 0x1eea0, 0x1eea3,
0x1eea4, 0x1eea9, 0x1eeaa, 0x1eebb, 0x1eeef, 0x1eef1, 0x1efff, 0x1f02b,
0x1f02f, 0x1f093, 0x1f09f, 0x1f0ae, 0x1f0b0, 0x1f0bf, 0x1f0c0, 0x1f0cf,
0x1f0d0, 0x1f0f5, 0x1f0ff, 0x1f10c, 0x1f10f, 0x1f16c, 0x1f16f, 0x1f1ac,
0x1f1e5, 0x1f202, 0x1f20f, 0x1f23b, 0x1f23f, 0x1f248, 0x1f24f, 0x1f251,
0x1f25f, 0x1f265, 0x1f2ff, 0x1f6d5, 0x1f6df, 0x1f6ec, 0x1f6ef, 0x1f6fa,
0x1f6ff, 0x1f773, 0x1f77f, 0x1f7d8, 0x1f7df, 0x1f7eb, 0x1f7ff, 0x1f80b,
0x1f80f, 0x1f847, 0x1f84f, 0x1f859, 0x1f85f, 0x1f887, 0x1f88f, 0x1f8ad,
0x1f8ff, 0x1f90b, 0x1f90c, 0x1f971, 0x1f972, 0x1f976, 0x1f979, 0x1f9a2,
0x1f9a4, 0x1f9aa, 0x1f9ad, 0x1f9ca, 0x1f9cc, 0x1fa53, 0x1fa5f, 0x1fa6d,
0x1fa6f, 0x1fa73, 0x1fa77, 0x1fa7a, 0x1fa7f, 0x1fa82, 0x1fa8f, 0x1fa95,
0x1ffff, 0x2a6d6, 0x2a6ff, 0x2b734, 0x2b73f, 0x2b81d, 0x2b81f, 0x2cea1,
0x2ceaf, 0x2ebe0, 0x2f7ff, 0x2fa1d, 0xe00ff, 0xe01ef, 0x10fffe,
};
static const bool is_printable[] = {
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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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,
};