annotate contrib/unicode/from_glibc/utf8_gen.py @ 145:1830386684a0

gcc-9.2.0
author anatofuz
date Thu, 13 Feb 2020 11:34:05 +0900
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
145
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1 #!/usr/bin/python3
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2 # -*- coding: utf-8 -*-
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3 # Copyright (C) 2014-2019 Free Software Foundation, Inc.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
4 # This file is part of the GNU C Library.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
5 #
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
6 # The GNU C Library is free software; you can redistribute it and/or
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
7 # modify it under the terms of the GNU Lesser General Public
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
8 # License as published by the Free Software Foundation; either
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
9 # version 2.1 of the License, or (at your option) any later version.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
10 #
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
11 # The GNU C Library is distributed in the hope that it will be useful,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
14 # Lesser General Public License for more details.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
15 #
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
16 # You should have received a copy of the GNU Lesser General Public
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
17 # License along with the GNU C Library; if not, see
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
18 # <https://www.gnu.org/licenses/>.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
19
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
20 '''glibc/localedata/charmaps/UTF-8 file generator script
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
21
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
22 This script generates a glibc/localedata/charmaps/UTF-8 file
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
23 from Unicode data.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
24
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
25 Usage: python3 utf8_gen.py UnicodeData.txt EastAsianWidth.txt
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
26
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
27 It will output UTF-8 file
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
28 '''
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
29
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
30 import argparse
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
31 import sys
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
32 import re
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
33 import unicode_utils
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
34
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
35 # Auxiliary tables for Hangul syllable names, see the Unicode 3.0 book,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
36 # sections 3.11 and 4.4.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
37
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
38 JAMO_INITIAL_SHORT_NAME = (
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
39 'G', 'GG', 'N', 'D', 'DD', 'R', 'M', 'B', 'BB', 'S', 'SS', '', 'J', 'JJ',
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
40 'C', 'K', 'T', 'P', 'H'
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
41 )
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
42
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
43 JAMO_MEDIAL_SHORT_NAME = (
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
44 'A', 'AE', 'YA', 'YAE', 'EO', 'E', 'YEO', 'YE', 'O', 'WA', 'WAE', 'OE',
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
45 'YO', 'U', 'WEO', 'WE', 'WI', 'YU', 'EU', 'YI', 'I'
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
46 )
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
47
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
48 JAMO_FINAL_SHORT_NAME = (
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
49 '', 'G', 'GG', 'GS', 'N', 'NI', 'NH', 'D', 'L', 'LG', 'LM', 'LB', 'LS',
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
50 'LT', 'LP', 'LH', 'M', 'B', 'BS', 'S', 'SS', 'NG', 'J', 'C', 'K', 'T',
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
51 'P', 'H'
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
52 )
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
53
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
54 def process_range(start, end, outfile, name):
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
55 '''Writes a range of code points into the CHARMAP section of the
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
56 output file
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
57
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
58 '''
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
59 if 'Hangul Syllable' in name:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
60 # from glibc/localedata/ChangeLog:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
61 #
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
62 # 2000-09-24 Bruno Haible <haible@clisp.cons.org>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
63 # * charmaps/UTF-8: Expand <Hangul Syllable> and <Private Use> ranges,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
64 # so they become printable and carry a width. Comment out surrogate
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
65 # ranges. Add a WIDTH table
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
66 #
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
67 # So we expand the Hangul Syllables here:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
68 for i in range(int(start, 16), int(end, 16)+1 ):
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
69 index2, index3 = divmod(i - 0xaC00, 28)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
70 index1, index2 = divmod(index2, 21)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
71 hangul_syllable_name = 'HANGUL SYLLABLE ' \
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
72 + JAMO_INITIAL_SHORT_NAME[index1] \
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
73 + JAMO_MEDIAL_SHORT_NAME[index2] \
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
74 + JAMO_FINAL_SHORT_NAME[index3]
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
75 outfile.write('{:<11s} {:<12s} {:s}\n'.format(
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
76 unicode_utils.ucs_symbol(i), convert_to_hex(i),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
77 hangul_syllable_name))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
78 return
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
79 # UnicodeData.txt file has contains code point ranges like this:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
80 #
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
81 # 3400;<CJK Ideograph Extension A, First>;Lo;0;L;;;;;N;;;;;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
82 # 4DB5;<CJK Ideograph Extension A, Last>;Lo;0;L;;;;;N;;;;;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
83 #
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
84 # The glibc UTF-8 file splits ranges like these into shorter
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
85 # ranges of 64 code points each:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
86 #
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
87 # <U3400>..<U343F> /xe3/x90/x80 <CJK Ideograph Extension A>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
88 # …
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
89 # <U4D80>..<U4DB5> /xe4/xb6/x80 <CJK Ideograph Extension A>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
90 for i in range(int(start, 16), int(end, 16), 64 ):
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
91 if i > (int(end, 16)-64):
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
92 outfile.write('{:s}..{:s} {:<12s} {:s}\n'.format(
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
93 unicode_utils.ucs_symbol(i),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
94 unicode_utils.ucs_symbol(int(end,16)),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
95 convert_to_hex(i),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
96 name))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
97 break
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
98 outfile.write('{:s}..{:s} {:<12s} {:s}\n'.format(
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
99 unicode_utils.ucs_symbol(i),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
100 unicode_utils.ucs_symbol(i+63),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
101 convert_to_hex(i),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
102 name))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
103
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
104 def process_charmap(flines, outfile):
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
105 '''This function takes an array which contains *all* lines of
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
106 of UnicodeData.txt and write lines to outfile as used in the
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
107
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
108 CHARMAP
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
109
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
110 END CHARMAP
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
111
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
112 section of the UTF-8 file in glibc/localedata/charmaps/UTF-8.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
113
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
114 Samples for input lines:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
115
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
116 0010;<control>;Cc;0;BN;;;;;N;DATA LINK ESCAPE;;;;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
117 3400;<CJK Ideograph Extension A, First>;Lo;0;L;;;;;N;;;;;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
118 4DB5;<CJK Ideograph Extension A, Last>;Lo;0;L;;;;;N;;;;;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
119 D800;<Non Private Use High Surrogate, First>;Cs;0;L;;;;;N;;;;;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
120 DB7F;<Non Private Use High Surrogate, Last>;Cs;0;L;;;;;N;;;;;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
121 100000;<Plane 16 Private Use, First>;Co;0;L;;;;;N;;;;;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
122 10FFFD;<Plane 16 Private Use, Last>;Co;0;L;;;;;N;;;;;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
123
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
124 Samples for output lines (Unicode-Value UTF-8-HEX Unicode-Char-Name):
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
125
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
126 <U0010> /x10 DATA LINK ESCAPE
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
127 <U3400>..<U343F> /xe3/x90/x80 <CJK Ideograph Extension A>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
128 %<UD800> /xed/xa0/x80 <Non Private Use High Surrogate, First>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
129 %<UDB7F> /xed/xad/xbf <Non Private Use High Surrogate, Last>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
130 <U0010FFC0>..<U0010FFFD> /xf4/x8f/xbf/x80 <Plane 16 Private Use>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
131
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
132 '''
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
133 fields_start = []
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
134 for line in flines:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
135 fields = line.split(";")
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
136 # Some characters have “<control>” as their name. We try to
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
137 # use the “Unicode 1.0 Name” (10th field in
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
138 # UnicodeData.txt) for them.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
139 #
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
140 # The Characters U+0080, U+0081, U+0084 and U+0099 have
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
141 # “<control>” as their name but do not even have aa
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
142 # ”Unicode 1.0 Name”. We could write code to take their
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
143 # alternate names from NameAliases.txt.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
144 if fields[1] == "<control>" and fields[10]:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
145 fields[1] = fields[10]
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
146 # Handling code point ranges like:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
147 #
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
148 # 3400;<CJK Ideograph Extension A, First>;Lo;0;L;;;;;N;;;;;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
149 # 4DB5;<CJK Ideograph Extension A, Last>;Lo;0;L;;;;;N;;;;;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
150 if fields[1].endswith(', First>') and not 'Surrogate,' in fields[1]:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
151 fields_start = fields
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
152 continue
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
153 if fields[1].endswith(', Last>') and not 'Surrogate,' in fields[1]:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
154 process_range(fields_start[0], fields[0],
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
155 outfile, fields[1][:-7]+'>')
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
156 fields_start = []
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
157 continue
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
158 fields_start = []
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
159 if 'Surrogate,' in fields[1]:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
160 # Comment out the surrogates in the UTF-8 file.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
161 # One could of course skip them completely but
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
162 # the original UTF-8 file in glibc had them as
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
163 # comments, so we keep these comment lines.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
164 outfile.write('%')
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
165 outfile.write('{:<11s} {:<12s} {:s}\n'.format(
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
166 unicode_utils.ucs_symbol(int(fields[0], 16)),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
167 convert_to_hex(int(fields[0], 16)),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
168 fields[1]))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
169
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
170 def convert_to_hex(code_point):
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
171 '''Converts a code point to a hexadecimal UTF-8 representation
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
172 like /x**/x**/x**.'''
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
173 # Getting UTF8 of Unicode characters.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
174 # In Python3, .encode('UTF-8') does not work for
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
175 # surrogates. Therefore, we use this conversion table
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
176 surrogates = {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
177 0xD800: '/xed/xa0/x80',
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
178 0xDB7F: '/xed/xad/xbf',
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
179 0xDB80: '/xed/xae/x80',
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
180 0xDBFF: '/xed/xaf/xbf',
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
181 0xDC00: '/xed/xb0/x80',
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
182 0xDFFF: '/xed/xbf/xbf',
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
183 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
184 if code_point in surrogates:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
185 return surrogates[code_point]
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
186 return ''.join([
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
187 '/x{:02x}'.format(c) for c in chr(code_point).encode('UTF-8')
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
188 ])
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
189
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
190 def write_header_charmap(outfile):
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
191 '''Write the header on top of the CHARMAP section to the output file'''
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
192 outfile.write("<code_set_name> UTF-8\n")
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
193 outfile.write("<comment_char> %\n")
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
194 outfile.write("<escape_char> /\n")
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
195 outfile.write("<mb_cur_min> 1\n")
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
196 outfile.write("<mb_cur_max> 6\n\n")
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
197 outfile.write("% CHARMAP generated using utf8_gen.py\n")
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
198 outfile.write("% alias ISO-10646/UTF-8\n")
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
199 outfile.write("CHARMAP\n")
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
200
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
201 def write_header_width(outfile, unicode_version):
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
202 '''Writes the header on top of the WIDTH section to the output file'''
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
203 outfile.write('% Character width according to Unicode '
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
204 + '{:s}.\n'.format(unicode_version))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
205 outfile.write('% - Default width is 1.\n')
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
206 outfile.write('% - Double-width characters have width 2; generated from\n')
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
207 outfile.write('% "grep \'^[^;]*;[WF]\' EastAsianWidth.txt"\n')
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
208 outfile.write('% - Non-spacing characters have width 0; '
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
209 + 'generated from PropList.txt or\n')
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
210 outfile.write('% "grep \'^[^;]*;[^;]*;[^;]*;[^;]*;NSM;\' '
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
211 + 'UnicodeData.txt"\n')
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
212 outfile.write('% - Format control characters have width 0; '
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
213 + 'generated from\n')
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
214 outfile.write("% \"grep '^[^;]*;[^;]*;Cf;' UnicodeData.txt\"\n")
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
215 # Not needed covered by Cf
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
216 # outfile.write("% - Zero width characters have width 0; generated from\n")
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
217 # outfile.write("% \"grep '^[^;]*;ZERO WIDTH ' UnicodeData.txt\"\n")
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
218 outfile.write("WIDTH\n")
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
219
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
220 def process_width(outfile, ulines, elines, plines):
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
221 '''ulines are lines from UnicodeData.txt, elines are lines from
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
222 EastAsianWidth.txt containing characters with width “W” or “F”,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
223 plines are lines from PropList.txt which contain characters
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
224 with the property “Prepended_Concatenation_Mark”.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
225
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
226 '''
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
227 width_dict = {}
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
228 for line in elines:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
229 fields = line.split(";")
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
230 if not '..' in fields[0]:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
231 code_points = (fields[0], fields[0])
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
232 else:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
233 code_points = fields[0].split("..")
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
234 for key in range(int(code_points[0], 16),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
235 int(code_points[1], 16)+1):
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
236 width_dict[key] = 2
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
237
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
238 for line in ulines:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
239 fields = line.split(";")
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
240 if fields[4] == "NSM" or fields[2] in ("Cf", "Me", "Mn"):
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
241 width_dict[int(fields[0], 16)] = 0
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
242
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
243 for line in plines:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
244 # Characters with the property “Prepended_Concatenation_Mark”
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
245 # should have the width 1:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
246 fields = line.split(";")
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
247 if not '..' in fields[0]:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
248 code_points = (fields[0], fields[0])
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
249 else:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
250 code_points = fields[0].split("..")
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
251 for key in range(int(code_points[0], 16),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
252 int(code_points[1], 16)+1):
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
253 del width_dict[key] # default width is 1
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
254
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
255 # handle special cases for compatibility
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
256 for key in list((0x00AD,)):
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
257 # https://www.cs.tut.fi/~jkorpela/shy.html
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
258 if key in width_dict:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
259 del width_dict[key] # default width is 1
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
260 for key in list(range(0x1160, 0x1200)):
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
261 width_dict[key] = 0
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
262 for key in list(range(0x3248, 0x3250)):
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
263 # These are “A” which means we can decide whether to treat them
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
264 # as “W” or “N” based on context:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
265 # http://www.unicode.org/mail-arch/unicode-ml/y2017-m08/0023.html
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
266 # For us, “W” seems better.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
267 width_dict[key] = 2
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
268 for key in list(range(0x4DC0, 0x4E00)):
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
269 width_dict[key] = 2
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
270
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
271 same_width_lists = []
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
272 current_width_list = []
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
273 for key in sorted(width_dict):
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
274 if not current_width_list:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
275 current_width_list = [key]
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
276 elif (key == current_width_list[-1] + 1
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
277 and width_dict[key] == width_dict[current_width_list[0]]):
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
278 current_width_list.append(key)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
279 else:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
280 same_width_lists.append(current_width_list)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
281 current_width_list = [key]
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
282 if current_width_list:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
283 same_width_lists.append(current_width_list)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
284
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
285 for same_width_list in same_width_lists:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
286 if len(same_width_list) == 1:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
287 outfile.write('{:s}\t{:d}\n'.format(
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
288 unicode_utils.ucs_symbol(same_width_list[0]),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
289 width_dict[same_width_list[0]]))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
290 else:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
291 outfile.write('{:s}...{:s}\t{:d}\n'.format(
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
292 unicode_utils.ucs_symbol(same_width_list[0]),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
293 unicode_utils.ucs_symbol(same_width_list[-1]),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
294 width_dict[same_width_list[0]]))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
295
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
296 if __name__ == "__main__":
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
297 PARSER = argparse.ArgumentParser(
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
298 description='''
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
299 Generate a UTF-8 file from UnicodeData.txt, EastAsianWidth.txt, and PropList.txt.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
300 ''')
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
301 PARSER.add_argument(
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
302 '-u', '--unicode_data_file',
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
303 nargs='?',
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
304 type=str,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
305 default='UnicodeData.txt',
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
306 help=('The UnicodeData.txt file to read, '
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
307 + 'default: %(default)s'))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
308 PARSER.add_argument(
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
309 '-e', '--east_asian_with_file',
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
310 nargs='?',
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
311 type=str,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
312 default='EastAsianWidth.txt',
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
313 help=('The EastAsianWidth.txt file to read, '
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
314 + 'default: %(default)s'))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
315 PARSER.add_argument(
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
316 '-p', '--prop_list_file',
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
317 nargs='?',
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
318 type=str,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
319 default='PropList.txt',
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
320 help=('The PropList.txt file to read, '
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
321 + 'default: %(default)s'))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
322 PARSER.add_argument(
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
323 '--unicode_version',
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
324 nargs='?',
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
325 required=True,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
326 type=str,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
327 help='The Unicode version of the input files used.')
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
328 ARGS = PARSER.parse_args()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
329
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
330 with open(ARGS.unicode_data_file, mode='r') as UNIDATA_FILE:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
331 UNICODE_DATA_LINES = UNIDATA_FILE.readlines()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
332 with open(ARGS.east_asian_with_file, mode='r') as EAST_ASIAN_WIDTH_FILE:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
333 EAST_ASIAN_WIDTH_LINES = []
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
334 for LINE in EAST_ASIAN_WIDTH_FILE:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
335 # If characters from EastAasianWidth.txt which are from
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
336 # from reserved ranges (i.e. not yet assigned code points)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
337 # are added to the WIDTH section of the UTF-8 file, then
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
338 # “make check” produces “Unknown Character” errors for
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
339 # these code points because such unassigned code points
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
340 # are not in the CHARMAP section of the UTF-8 file.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
341 #
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
342 # Therefore, we skip all reserved code points when reading
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
343 # the EastAsianWidth.txt file.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
344 if re.match(r'.*<reserved-.+>\.\.<reserved-.+>.*', LINE):
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
345 continue
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
346 if re.match(r'^[^;]*;[WF]', LINE):
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
347 EAST_ASIAN_WIDTH_LINES.append(LINE.strip())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
348 with open(ARGS.prop_list_file, mode='r') as PROP_LIST_FILE:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
349 PROP_LIST_LINES = []
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
350 for LINE in PROP_LIST_FILE:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
351 if re.match(r'^[^;]*;[\s]*Prepended_Concatenation_Mark', LINE):
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
352 PROP_LIST_LINES.append(LINE.strip())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
353 with open('UTF-8', mode='w') as OUTFILE:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
354 # Processing UnicodeData.txt and write CHARMAP to UTF-8 file
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
355 write_header_charmap(OUTFILE)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
356 process_charmap(UNICODE_DATA_LINES, OUTFILE)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
357 OUTFILE.write("END CHARMAP\n\n")
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
358 # Processing EastAsianWidth.txt and write WIDTH to UTF-8 file
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
359 write_header_width(OUTFILE, ARGS.unicode_version)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
360 process_width(OUTFILE,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
361 UNICODE_DATA_LINES,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
362 EAST_ASIAN_WIDTH_LINES,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
363 PROP_LIST_LINES)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
364 OUTFILE.write("END WIDTH\n")