$CODE = 0;
$NAME = 1;
$CATEGORY = 2;
$COMBINING_CLASSES = 3;
$BIDI_CATEGORY = 4;
$DECOMPOSITION = 5;
$DECIMAL_VALUE = 6;
$DIGIT_VALUE = 7;
$NUMERIC_VALUE = 8;
$MIRRORED = 9;
$OLD_NAME = 10;
$COMMENT = 11;
$UPPER = 12;
$LOWER = 13;
$TITLE = 14;
%gaps = (
0x4e00 => "CJK",
0xac00 => "Hangul",
0xd800 => "Unassigned High Surrogate",
0xdb80 => "Private Use High Surrogate",
0xdc00 => "Low Surrogate",
0xe000 => "Private Use"
);
%whitespace_controls =
(
0x0009 => 1,
0x000a => 1,
0x000b => 1,
0x000c => 1,
0x000d => 1,
0x001c => 1,
0x001d => 1,
0x001e => 1,
0x001f => 1
);
open (INPUT, "< $ARGV[0]") || exit 1;
$last_code = -1;
while (<INPUT>)
{
chop;
@fields = split (';', $_, 30);
if ($ {
print STDERR "Entry for $fields[$CODE] has wrong number of fields\n";
}
$code = hex ($fields[$CODE]);
last if $code > 0xffff;
if ($code > $last_code + 1)
{
if (defined $gaps{$code})
{
@gfields = @fields;
}
else
{
@gfields = ('', '', 'Cn', '0', '', '', '', '', '', '', '',
'', '', '', '');
}
for (++$last_code; $last_code < $code; ++$last_code)
{
$gfields{$CODE} = sprintf ("%04x", $last_code);
&process_one ($last_code, @gfields);
}
}
&process_one ($code, @fields);
$last_code = $code;
}
close (INPUT);
@gfields = ('', '', 'Cn', '0', '', '', '', '', '', '', '',
'', '', '', '');
for (++$last_code; $last_code < 0x10000; ++$last_code)
{
$gfields{$CODE} = sprintf ("%04x", $last_code);
&process_one ($last_code, @gfields);
}
--$last_code;
&print_tables ($last_code);
exit 0;
sub process_one
{
my ($code, @fields) = @_;
my @value = ();
my $type = $fields[$CATEGORY];
if ($type =~ /L./ || $type eq 'Pc' || $type eq 'Sc') {
push (@value, 'LETTER_START');
}
if ($type =~ /L./ || $type eq 'Pc' || $type eq 'Sc' || $type =~ /N[dl]/ || $type =~ /M[nc]/ || ($type eq 'Cc' && ! defined $whitespace_controls{$code})
|| ($code >= 0x200c && $code <= 0x200f)
|| ($code >= 0x202a && $code <= 0x202e)
|| ($code >= 0x206a && $code <= 0x206f)
|| $code == 0xfeff) {
push (@value, 'LETTER_PART');
}
if (($type =~ /Z./
&& $code != 0x00a0
&& $code != 0x2007
&& $code != 0x202f)
|| $code == 0x000b
|| ($code >= 0x001c && $code <= 0x001f))
{
push (@value, 'LETTER_SPACE');
}
if (! @value)
{
$value = '0';
}
else
{
$value = '(' . join (' | ', @value) . ')';
}
$map[$code] = $value;
}
sub print_tables
{
my ($last) = @_;
local ($bytes_out) = 0;
open (OUT, "> chartables.h");
print OUT "/* This file is automatically generated. DO NOT EDIT!\n";
print OUT " Instead, edit gen-table.pl and re-run. */\n\n";
print OUT "#ifndef GCC_CHARTABLES_H\n";
print OUT "#define GCC_CHARTABLES_H\n\n";
print OUT "#define LETTER_START 1\n";
print OUT "#define LETTER_PART 2\n";
print OUT "#define LETTER_SPACE 4\n\n";
print OUT "#define LETTER_MASK 7\n\n";
for ($count = 0; $count <= $last; $count += 256)
{
$row[$count / 256] = &print_row ($count, '(char *) ', 'const char', 1,
'page');
}
print OUT "static const char *const type_table[256] = {\n";
for ($count = 0; $count <= $last; $count += 256)
{
print OUT ",\n" if $count > 0;
print OUT " ", $row[$count / 256];
$bytes_out += 4;
}
print OUT "\n};\n\n";
print OUT "#endif /* ! GCC_CHARTABLES_H */\n";
close (OUT);
printf "Generated %d bytes\n", $bytes_out;
}
sub print_row
{
my ($start, $def_pfx, $typname, $typsize, $name) = @_;
my ($i);
my (@values);
my ($flag) = 1;
my ($off);
for ($off = 0; $off < 256; ++$off)
{
$values[$off] = $map[$off + $start];
if ($values[$off] ne $values[0])
{
$flag = 0;
}
}
if ($flag)
{
return $def_pfx . $values[0];
}
printf OUT "static %s %s%d[256] = {\n ", $typname, $name, $start / 256;
my ($column) = 2;
for ($i = $start; $i < $start + 256; ++$i)
{
print OUT ", "
if $i > $start;
my ($text) = $values[$i - $start];
if (length ($text) + $column + 2 > 78)
{
print OUT "\n ";
$column = 2;
}
print OUT $text;
$column += length ($text) + 2;
}
print OUT "\n};\n\n";
$bytes_out += 256 * $typsize;
return sprintf "%s%d", $name, $start / 256;
}