1*b1cdbd2cSJim Jagielski#!/usr/bin/perl
2*b1cdbd2cSJim Jagielski#**************************************************************
3*b1cdbd2cSJim Jagielski#
4*b1cdbd2cSJim Jagielski#  Licensed to the Apache Software Foundation (ASF) under one
5*b1cdbd2cSJim Jagielski#  or more contributor license agreements.  See the NOTICE file
6*b1cdbd2cSJim Jagielski#  distributed with this work for additional information
7*b1cdbd2cSJim Jagielski#  regarding copyright ownership.  The ASF licenses this file
8*b1cdbd2cSJim Jagielski#  to you under the Apache License, Version 2.0 (the
9*b1cdbd2cSJim Jagielski#  "License"); you may not use this file except in compliance
10*b1cdbd2cSJim Jagielski#  with the License.  You may obtain a copy of the License at
11*b1cdbd2cSJim Jagielski#
12*b1cdbd2cSJim Jagielski#    http://www.apache.org/licenses/LICENSE-2.0
13*b1cdbd2cSJim Jagielski#
14*b1cdbd2cSJim Jagielski#  Unless required by applicable law or agreed to in writing,
15*b1cdbd2cSJim Jagielski#  software distributed under the License is distributed on an
16*b1cdbd2cSJim Jagielski#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17*b1cdbd2cSJim Jagielski#  KIND, either express or implied.  See the License for the
18*b1cdbd2cSJim Jagielski#  specific language governing permissions and limitations
19*b1cdbd2cSJim Jagielski#  under the License.
20*b1cdbd2cSJim Jagielski#
21*b1cdbd2cSJim Jagielski#**************************************************************
22*b1cdbd2cSJim Jagielski
23*b1cdbd2cSJim Jagielski
24*b1cdbd2cSJim Jagielski
25*b1cdbd2cSJim Jagielski# The following files must be available in a ./input subdir:
26*b1cdbd2cSJim Jagielski
27*b1cdbd2cSJim Jagielski# <http://oss.software.ibm.com/cvs/icu/~checkout~/charset/data/xml/
28*b1cdbd2cSJim Jagielski# gb-18030-2000.xml?rev=1.4&content-type=text/plain>:
29*b1cdbd2cSJim Jagielski#  "modified version="3" date="2001-02-21""
30*b1cdbd2cSJim Jagielski
31*b1cdbd2cSJim Jagielski$id = "Gb180302000";
32*b1cdbd2cSJim Jagielski
33*b1cdbd2cSJim Jagielskisub printUtf32
34*b1cdbd2cSJim Jagielski{
35*b1cdbd2cSJim Jagielski    my $utf32 = $_[0];
36*b1cdbd2cSJim Jagielski    return sprintf("U+%04X", $utf32);
37*b1cdbd2cSJim Jagielski}
38*b1cdbd2cSJim Jagielski
39*b1cdbd2cSJim Jagielskisub printGb
40*b1cdbd2cSJim Jagielski{
41*b1cdbd2cSJim Jagielski    if (defined($_[2]))
42*b1cdbd2cSJim Jagielski    {
43*b1cdbd2cSJim Jagielski        return sprintf("%02X%02X%02X%02X", $_[0], $_[1], $_[2], $_[3]);
44*b1cdbd2cSJim Jagielski    }
45*b1cdbd2cSJim Jagielski    elsif (defined($_[1]))
46*b1cdbd2cSJim Jagielski    {
47*b1cdbd2cSJim Jagielski        return sprintf("%02X%02X", $_[0], $_[1]);
48*b1cdbd2cSJim Jagielski    }
49*b1cdbd2cSJim Jagielski    else
50*b1cdbd2cSJim Jagielski    {
51*b1cdbd2cSJim Jagielski        return sprintf("%02X", $_[0]);
52*b1cdbd2cSJim Jagielski    }
53*b1cdbd2cSJim Jagielski}
54*b1cdbd2cSJim Jagielski
55*b1cdbd2cSJim Jagielski$gb_map_2_count = 0;
56*b1cdbd2cSJim Jagielski$gb_map_4_count = 0;
57*b1cdbd2cSJim Jagielski$gb_map_4_ranges = 0;
58*b1cdbd2cSJim Jagielski$gb_map_4_max = 0;
59*b1cdbd2cSJim Jagielski$uni_map_count = 0;
60*b1cdbd2cSJim Jagielski
61*b1cdbd2cSJim Jagielski$range_count = 0;
62*b1cdbd2cSJim Jagielski
63*b1cdbd2cSJim Jagielskiif (1)
64*b1cdbd2cSJim Jagielski{
65*b1cdbd2cSJim Jagielski    $filename = "gb-18030-2000.xml";
66*b1cdbd2cSJim Jagielski    open IN, ("input/" . $filename) or die "Cannot read " . $filename;
67*b1cdbd2cSJim Jagielski    while (<IN>)
68*b1cdbd2cSJim Jagielski    {
69*b1cdbd2cSJim Jagielski        if (/^[ \t]*<a +u=\"([0-9A-F]+)\" +b=\"([0-7][0-9A-F])\"\/>$/)
70*b1cdbd2cSJim Jagielski        {
71*b1cdbd2cSJim Jagielski            $utf32 = oct("0x" . $1);
72*b1cdbd2cSJim Jagielski            $gb1 = oct("0x" . $2);
73*b1cdbd2cSJim Jagielski            ($utf32 == $gb1)
74*b1cdbd2cSJim Jagielski                or die "Bad " . printUtf32($utf32) . " to " . printGb($gb1);
75*b1cdbd2cSJim Jagielski        }
76*b1cdbd2cSJim Jagielski        elsif (/^[ \t]*<a +u=\"([0-9A-F]+)\" +b=\"([89A-F][0-9A-F]) ([4-789A-F][0-9A-F])\"\/>$/)
77*b1cdbd2cSJim Jagielski        {
78*b1cdbd2cSJim Jagielski            $utf32 = oct("0x" . $1);
79*b1cdbd2cSJim Jagielski            $gb1 = oct("0x" . $2);
80*b1cdbd2cSJim Jagielski            $gb2 = oct("0x" . $3);
81*b1cdbd2cSJim Jagielski            $gb_code = ($gb1 - 0x81) * 190
82*b1cdbd2cSJim Jagielski                           + ($gb2 <= 0x7E ? $gb2 - 0x40 : $gb2 - 0x80 + 63);
83*b1cdbd2cSJim Jagielski            !defined($gb_map_2[$gb_code])
84*b1cdbd2cSJim Jagielski                or die "Redefined " . printGb($gb1, $gb2);
85*b1cdbd2cSJim Jagielski            $gb_map_2[$gb_code] = $utf32;
86*b1cdbd2cSJim Jagielski            ++$gb_map_2_count;
87*b1cdbd2cSJim Jagielski
88*b1cdbd2cSJim Jagielski            !defined($uni_map[$utf32]) or die "Double Unicode mapping";
89*b1cdbd2cSJim Jagielski            $uni_map[$utf32] = $gb1 << 8 | $gb2;
90*b1cdbd2cSJim Jagielski            ++$uni_map_count;
91*b1cdbd2cSJim Jagielski        }
92*b1cdbd2cSJim Jagielski        elsif (/^[ \t]*<a +u=\"([0-9A-F]+)\" +b=\"([89A-F][0-9A-F]) (3[0-9]) ([89A-F][0-9A-F]) (3[0-9])\"\/>$/)
93*b1cdbd2cSJim Jagielski        {
94*b1cdbd2cSJim Jagielski            $utf32 = oct("0x" . $1);
95*b1cdbd2cSJim Jagielski            $gb1 = oct("0x" . $2);
96*b1cdbd2cSJim Jagielski            $gb2 = oct("0x" . $3);
97*b1cdbd2cSJim Jagielski            $gb3 = oct("0x" . $4);
98*b1cdbd2cSJim Jagielski            $gb4 = oct("0x" . $5);
99*b1cdbd2cSJim Jagielski            $gb_code = ($gb1 - 0x81) * 12600
100*b1cdbd2cSJim Jagielski                           + ($gb2 - 0x30) * 1260
101*b1cdbd2cSJim Jagielski                           + ($gb3 - 0x81) * 10
102*b1cdbd2cSJim Jagielski                           + ($gb4 - 0x30);
103*b1cdbd2cSJim Jagielski            !defined($gb_map_4[$gb_code])
104*b1cdbd2cSJim Jagielski                or die "Redefined " . printGb($gb1, $gb2, $gb3, $gb4);
105*b1cdbd2cSJim Jagielski            $gb_map_4[$gb_code] = $utf32;
106*b1cdbd2cSJim Jagielski            ++$gb_map_4_count;
107*b1cdbd2cSJim Jagielski            $gb_map_4_max = $gb_code if ($gb_code > $gb_map_4_max);
108*b1cdbd2cSJim Jagielski
109*b1cdbd2cSJim Jagielski            !defined($uni_map[$utf32]) or die "Double Unicode mapping";
110*b1cdbd2cSJim Jagielski            $uni_map[$utf32] = $gb1 << 24 | $gb2 << 16 | $gb3 << 8 | $gb4;
111*b1cdbd2cSJim Jagielski            ++$uni_map_count;
112*b1cdbd2cSJim Jagielski        }
113*b1cdbd2cSJim Jagielski        elsif (/<a /)
114*b1cdbd2cSJim Jagielski        {
115*b1cdbd2cSJim Jagielski            die "Bad format";
116*b1cdbd2cSJim Jagielski        }
117*b1cdbd2cSJim Jagielski        elsif (/^[ \t]*<range +uFirst=\"([0-9A-F]+)\" +uLast=\"([0-9A-F]+)\" +bFirst=\"([89A-F][0-9A-F]) (3[0-9]) ([89A-F][0-9A-F]) (3[0-9])\" +bLast=\"([89A-F][0-9A-F]) (3[0-9]) ([89A-F][0-9A-F]) (3[0-9])\" +bMin=\"81 30 81 30\" +bMax=\"FE 39 FE 39\"\/>$/)
118*b1cdbd2cSJim Jagielski        {
119*b1cdbd2cSJim Jagielski            $utf32_first = oct("0x" . $1);
120*b1cdbd2cSJim Jagielski            $utf32_last = oct("0x" . $2);
121*b1cdbd2cSJim Jagielski            $gb1_first = oct("0x" . $3);
122*b1cdbd2cSJim Jagielski            $gb2_first = oct("0x" . $4);
123*b1cdbd2cSJim Jagielski            $gb3_first = oct("0x" . $5);
124*b1cdbd2cSJim Jagielski            $gb4_first = oct("0x" . $6);
125*b1cdbd2cSJim Jagielski            $gb1_last = oct("0x" . $7);
126*b1cdbd2cSJim Jagielski            $gb2_last = oct("0x" . $8);
127*b1cdbd2cSJim Jagielski            $gb3_last = oct("0x" . $9);
128*b1cdbd2cSJim Jagielski            $gb4_last = oct("0x" . $10);
129*b1cdbd2cSJim Jagielski            $linear_first
130*b1cdbd2cSJim Jagielski                = ($gb1_first - 0x81) * 12600
131*b1cdbd2cSJim Jagielski                    + ($gb2_first - 0x30) * 1260
132*b1cdbd2cSJim Jagielski                        + ($gb3_first - 0x81) * 10
133*b1cdbd2cSJim Jagielski                            + ($gb4_first - 0x30);
134*b1cdbd2cSJim Jagielski            $linear_last
135*b1cdbd2cSJim Jagielski                = ($gb1_last - 0x81) * 12600
136*b1cdbd2cSJim Jagielski                    + ($gb2_last - 0x30) * 1260
137*b1cdbd2cSJim Jagielski                        + ($gb3_last - 0x81) * 10
138*b1cdbd2cSJim Jagielski                            + ($gb4_last - 0x30);
139*b1cdbd2cSJim Jagielski            ($utf32_last - $utf32_first == $linear_last - $linear_first)
140*b1cdbd2cSJim Jagielski                or die "Bad range";
141*b1cdbd2cSJim Jagielski            if ($linear_first != 189000 || $linear_last != 1237575)
142*b1cdbd2cSJim Jagielski            {
143*b1cdbd2cSJim Jagielski                $range_uni_first[$range_count] = $utf32_first;
144*b1cdbd2cSJim Jagielski                $range_uni_last[$range_count]
145*b1cdbd2cSJim Jagielski                    = ($utf32_last == 0xD7FF ? 0xDFFF : $utf32_last);
146*b1cdbd2cSJim Jagielski                $range_linear_first[$range_count] = $linear_first;
147*b1cdbd2cSJim Jagielski                $range_linear_last[$range_count] = $linear_last;
148*b1cdbd2cSJim Jagielski                ++$range_count;
149*b1cdbd2cSJim Jagielski                $gb_map_4_ranges += $linear_last - $linear_first + 1;
150*b1cdbd2cSJim Jagielski                $gb_map_4_max = $linear_last
151*b1cdbd2cSJim Jagielski                    if ($linear_last > $gb_map_4_max);
152*b1cdbd2cSJim Jagielski            }
153*b1cdbd2cSJim Jagielski        }
154*b1cdbd2cSJim Jagielski        elsif (/<range /)
155*b1cdbd2cSJim Jagielski        {
156*b1cdbd2cSJim Jagielski            die "Bad format";
157*b1cdbd2cSJim Jagielski        }
158*b1cdbd2cSJim Jagielski    }
159*b1cdbd2cSJim Jagielski    close IN;
160*b1cdbd2cSJim Jagielski}
161*b1cdbd2cSJim Jagielski
162*b1cdbd2cSJim Jagielskiprint "gb_map_2_count = ", $gb_map_2_count,
163*b1cdbd2cSJim Jagielski      ", gb_map_4_count = ", $gb_map_4_count,
164*b1cdbd2cSJim Jagielski      ", gb_map_4_ranges = ", $gb_map_4_ranges,
165*b1cdbd2cSJim Jagielski      ", gb_map_4_max = ", $gb_map_4_max,
166*b1cdbd2cSJim Jagielski      ", uni_map_count = ", $uni_map_count, "\n";
167*b1cdbd2cSJim Jagielski($gb_map_2_count == 23940) or die "Bad gb_map_2_count != 23940";
168*b1cdbd2cSJim Jagielski($gb_map_4_max == $gb_map_4_count + $gb_map_4_ranges - 1)
169*b1cdbd2cSJim Jagielski    or die "Bad gb_map_4_max != gb_map_4_count + gb_map_4_ranges";
170*b1cdbd2cSJim Jagielski($uni_map_count + $gb_map_4_ranges == 0x10000 - (0xE000 - 0xD800) - 0x80)
171*b1cdbd2cSJim Jagielski    or die "Bad uni_map_count";
172*b1cdbd2cSJim Jagielski
173*b1cdbd2cSJim Jagielski$range_index = 0;
174*b1cdbd2cSJim Jagielski$gb_nonrangedataindex[$range_index] = $gb_map_2_count;
175*b1cdbd2cSJim Jagielskifor ($gb_code = 0; $gb_code < $gb_map_4_max; ++$gb_code)
176*b1cdbd2cSJim Jagielski{
177*b1cdbd2cSJim Jagielski    if (defined($gb_map_4[$gb_code]))
178*b1cdbd2cSJim Jagielski    {
179*b1cdbd2cSJim Jagielski        $gb_map_2[$gb_map_2_count++] = $gb_map_4[$gb_code];
180*b1cdbd2cSJim Jagielski    }
181*b1cdbd2cSJim Jagielski    else
182*b1cdbd2cSJim Jagielski    {
183*b1cdbd2cSJim Jagielski        ($gb_code == $range_linear_first[$range_index]) or die "Bad input";
184*b1cdbd2cSJim Jagielski        $gb_code = $range_linear_last[$range_index];
185*b1cdbd2cSJim Jagielski        ++$range_index;
186*b1cdbd2cSJim Jagielski        $gb_nonrangedataindex[$range_index] = $gb_map_2_count;
187*b1cdbd2cSJim Jagielski    }
188*b1cdbd2cSJim Jagielski}
189*b1cdbd2cSJim Jagielski($range_index == $range_count) or die "Bad input";
190*b1cdbd2cSJim Jagielski
191*b1cdbd2cSJim Jagielski$filename = lc($id) . ".tab";
192*b1cdbd2cSJim Jagielskiopen OUT, ("> " . $filename) or die "Cannot write " . $filename;
193*b1cdbd2cSJim Jagielski
194*b1cdbd2cSJim Jagielski{
195*b1cdbd2cSJim Jagielski    $filename = lc($id). ".pl";
196*b1cdbd2cSJim Jagielski    open IN, $filename or die "Cannot read ". $filename;
197*b1cdbd2cSJim Jagielski    $first = 1;
198*b1cdbd2cSJim Jagielski    while (<IN>)
199*b1cdbd2cSJim Jagielski    {
200*b1cdbd2cSJim Jagielski        if (/^\#!.*$/)
201*b1cdbd2cSJim Jagielski        {
202*b1cdbd2cSJim Jagielski        }
203*b1cdbd2cSJim Jagielski        elsif (/^\#(\*.*)$/)
204*b1cdbd2cSJim Jagielski        {
205*b1cdbd2cSJim Jagielski            if ($first == 1)
206*b1cdbd2cSJim Jagielski            {
207*b1cdbd2cSJim Jagielski                print OUT "/", $1, "\n";
208*b1cdbd2cSJim Jagielski                $first = 0;
209*b1cdbd2cSJim Jagielski            }
210*b1cdbd2cSJim Jagielski            else
211*b1cdbd2cSJim Jagielski            {
212*b1cdbd2cSJim Jagielski                print OUT " ", substr($1, 0, length($1) - 1), "/\n";
213*b1cdbd2cSJim Jagielski            }
214*b1cdbd2cSJim Jagielski        }
215*b1cdbd2cSJim Jagielski        elsif (/^\# (.*)$/)
216*b1cdbd2cSJim Jagielski        {
217*b1cdbd2cSJim Jagielski            print OUT " *", $1, "\n";
218*b1cdbd2cSJim Jagielski        }
219*b1cdbd2cSJim Jagielski        elsif (/^\#(.*)$/)
220*b1cdbd2cSJim Jagielski        {
221*b1cdbd2cSJim Jagielski            print OUT " *", $1, "\n";
222*b1cdbd2cSJim Jagielski        }
223*b1cdbd2cSJim Jagielski        else
224*b1cdbd2cSJim Jagielski        {
225*b1cdbd2cSJim Jagielski            goto done;
226*b1cdbd2cSJim Jagielski        }
227*b1cdbd2cSJim Jagielski    }
228*b1cdbd2cSJim Jagielski  done:
229*b1cdbd2cSJim Jagielski}
230*b1cdbd2cSJim Jagielski
231*b1cdbd2cSJim Jagielskiprint OUT "\n",
232*b1cdbd2cSJim Jagielski          "#ifndef INCLUDED_RTL_TEXTENC_CONVERTGB18030_H\n",
233*b1cdbd2cSJim Jagielski          "#include \"convertgb18030.h\"\n",
234*b1cdbd2cSJim Jagielski          "#endif\n",
235*b1cdbd2cSJim Jagielski          "\n",
236*b1cdbd2cSJim Jagielski          "#ifndef _SAL_TYPES_H_\n",
237*b1cdbd2cSJim Jagielski          "#include \"sal/types.h\"\n",
238*b1cdbd2cSJim Jagielski          "#endif\n",
239*b1cdbd2cSJim Jagielski          "\n";
240*b1cdbd2cSJim Jagielski
241*b1cdbd2cSJim Jagielskiprint OUT "static sal_Unicode const aImpl", $id, "ToUnicodeData[] = {\n  ";
242*b1cdbd2cSJim Jagielskifor ($gb_code = 0; $gb_code < $gb_map_2_count; ++$gb_code)
243*b1cdbd2cSJim Jagielski{
244*b1cdbd2cSJim Jagielski    printf OUT "0x%04X,", $gb_map_2[$gb_code];
245*b1cdbd2cSJim Jagielski    if ($gb_code % 8 == 7 && $gb_code != $gb_map_2_count - 1)
246*b1cdbd2cSJim Jagielski    {
247*b1cdbd2cSJim Jagielski        print OUT "\n  ";
248*b1cdbd2cSJim Jagielski    }
249*b1cdbd2cSJim Jagielski}
250*b1cdbd2cSJim Jagielskiprint OUT "\n};\n\n";
251*b1cdbd2cSJim Jagielski
252*b1cdbd2cSJim Jagielskiprint OUT "static ImplGb180302000ToUnicodeRange const\n    aImpl",
253*b1cdbd2cSJim Jagielski          $id,
254*b1cdbd2cSJim Jagielski          "ToUnicodeRanges[] = {\n";
255*b1cdbd2cSJim Jagielskifor ($range_index = 0; $range_index < $range_count; ++$range_index)
256*b1cdbd2cSJim Jagielski{
257*b1cdbd2cSJim Jagielski    printf OUT "  { %d, %d, %d, 0x%04X },\n",
258*b1cdbd2cSJim Jagielski               $gb_nonrangedataindex[$range_index],
259*b1cdbd2cSJim Jagielski               $range_linear_first[$range_index],
260*b1cdbd2cSJim Jagielski               $range_linear_last[$range_index] + 1,
261*b1cdbd2cSJim Jagielski               $range_uni_first[$range_index];
262*b1cdbd2cSJim Jagielski}
263*b1cdbd2cSJim Jagielskiprint OUT "  { -1, 0, 0, 0 }\n};\n\n";
264*b1cdbd2cSJim Jagielski
265*b1cdbd2cSJim Jagielskiprint OUT "static sal_uInt32 const aImplUnicodeTo", $id, "Data[] = {\n  ";
266*b1cdbd2cSJim Jagielski$index = 0;
267*b1cdbd2cSJim Jagielski$range_index = 0;
268*b1cdbd2cSJim Jagielski$uni_nonrangedataindex[$range_index] = $index;
269*b1cdbd2cSJim Jagielskifor ($utf32 = 0x80; $utf32 <= 0xFFFF; ++$utf32)
270*b1cdbd2cSJim Jagielski{
271*b1cdbd2cSJim Jagielski    if (defined($uni_map[$utf32]))
272*b1cdbd2cSJim Jagielski    {
273*b1cdbd2cSJim Jagielski        if ($index > 0 && ($index - 1) % 6 == 5)
274*b1cdbd2cSJim Jagielski        {
275*b1cdbd2cSJim Jagielski            print OUT "\n  ";
276*b1cdbd2cSJim Jagielski        }
277*b1cdbd2cSJim Jagielski        $bytes = $uni_map[$utf32];
278*b1cdbd2cSJim Jagielski        printf OUT ($bytes <= 0xFFFF ? "    0x%04X," : "0x%08X,"), $bytes;
279*b1cdbd2cSJim Jagielski        ++$index;
280*b1cdbd2cSJim Jagielski    }
281*b1cdbd2cSJim Jagielski    else
282*b1cdbd2cSJim Jagielski    {
283*b1cdbd2cSJim Jagielski        ($utf32 == $range_uni_first[$range_index]) or die "Bad input";
284*b1cdbd2cSJim Jagielski        $utf32 = $range_uni_last[$range_index];
285*b1cdbd2cSJim Jagielski        ++$range_index;
286*b1cdbd2cSJim Jagielski        $uni_nonrangedataindex[$range_index] = $index;
287*b1cdbd2cSJim Jagielski    }
288*b1cdbd2cSJim Jagielski}
289*b1cdbd2cSJim Jagielski($range_index == $range_count) or die "Bad input";
290*b1cdbd2cSJim Jagielskiprint OUT "\n};\n\n";
291*b1cdbd2cSJim Jagielski
292*b1cdbd2cSJim Jagielskiprint OUT "static ImplUnicodeToGb180302000Range const\n    aImplUnicodeTo",
293*b1cdbd2cSJim Jagielski          $id,
294*b1cdbd2cSJim Jagielski          "Ranges[] = {\n";
295*b1cdbd2cSJim Jagielskifor ($range_index = 0; $range_index < $range_count; ++$range_index)
296*b1cdbd2cSJim Jagielski{
297*b1cdbd2cSJim Jagielski    printf OUT "  { %d, 0x%04X, 0x%04X, %d },\n",
298*b1cdbd2cSJim Jagielski               $uni_nonrangedataindex[$range_index],
299*b1cdbd2cSJim Jagielski               $range_uni_first[$range_index],
300*b1cdbd2cSJim Jagielski               $range_uni_last[$range_index],
301*b1cdbd2cSJim Jagielski               $range_linear_first[$range_index];
302*b1cdbd2cSJim Jagielski}
303*b1cdbd2cSJim Jagielskiprint OUT "};\n";
304*b1cdbd2cSJim Jagielski
305*b1cdbd2cSJim Jagielskiclose OUT;
306