xorg-libx11/nls/compose-check.pl
Alan Coopersmith 3843778358 Add perl script to check for duplicate or conflicting compose file entries
Signed-off-by: Alan Coopersmith <alan.coopersmith@sun.com>
2009-09-18 17:13:05 -07:00

163 lines
4.8 KiB
Perl
Executable file

#! /usr/bin/perl
#
# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, and/or sell copies of the Software, and to permit persons
# to whom the Software is furnished to do so, provided that the above
# copyright notice(s) and this permission notice appear in all copies of
# the Software and that both the above copyright notice(s) and this
# permission notice appear in supporting documentation.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
# OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
# HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
# INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# Except as contained in this notice, the name of a copyright holder
# shall not be used in advertising or otherwise to promote the sale, use
# or other dealings in this Software without prior written authorization
# of the copyright holder.
#
#
# Check a compose file for duplicate/conflicting entries and other common errors
#
# Compose file grammar is defined in modules/im/ximcp/imLcPrs.c
use strict;
use warnings;
my $error_count = 0;
if (scalar(@ARGV) == 0) {
push @ARGV, "Compose";
}
foreach my $cf (@ARGV) {
$error_count += check_compose_file($cf);
}
exit($error_count);
sub check_compose_file {
my ($filename) = @_;
my $errors = 0;
my %compose_table = ();
my $line = 0;
my $pre_file = ($filename =~ m{\.pre$}) ? 1 : 0;
my $in_c_comment = 0;
open my $COMPOSE, '<', $filename or die "Could not open $filename: $!";
COMPOSE_LINE:
while (my $cl = <$COMPOSE>) {
$line++;
chomp($cl);
my $original_line = $cl;
# Special handling for changes cpp makes to .pre files
if ($pre_file == 1) {
if ($in_c_comment) { # Look for end of multi-line C comment
if ($cl =~ m{\*/(.*)$}) {
$cl = $1;
$in_c_comment = 0;
} else {
next;
}
}
$cl =~ s{/\*.\**/}{}; # Remove single line C comments
if ($cl =~ m{^(.*)/\*}) { # Start of a multi-line C comment
$cl = $1;
$in_c_comment = 1;
}
next if $cl =~ m{^\s*XCOMM}; # Skip pre-processing comments
}
$cl =~ s{#.*$}{}; # Remove comments
next if $cl =~ m{^\s*$}; # Skip blank (or comment-only) lines
chomp($cl);
if ($cl =~ m{^(STATE\s+|END_STATE)}) { # Sun extension to compose file syntax
%compose_table = ();
}
elsif ($cl =~ m{^([^:]+)\s*:\s*(.+)$}) {
my ($seq, $action) = ($1, $2);
$seq =~ s{\s+$}{};
my @keys = grep { $_ !~ m/^\s*$/ } split /[\s\<\>]+/, $seq;
my $final_key = pop @keys;
my $keytable = \%compose_table;
foreach my $k (@keys) {
if ($k =~ m{^U([[:xdigit:]]+)$}) {
$k = 'U' . lc($1);
}
if (exists $keytable->{$k}) {
$keytable = $keytable->{$k};
if (ref($keytable) ne 'HASH') {
print
"Clash with existing sequence in $filename on line $line: $seq\n";
print_sequences([$line, $original_line]);
print_sequences($keytable);
$errors++;
next COMPOSE_LINE;
}
} else {
my $new_keytable = {};
$keytable->{$k} = $new_keytable;
$keytable = $new_keytable;
}
}
if (exists $keytable->{$final_key}) {
print "Clash with existing sequence in $filename on line $line: $seq\n";
print_sequences([$line, $original_line]);
print_sequences($keytable->{$final_key});
$errors++;
} else {
$keytable->{$final_key} = [$line, $original_line];
}
} elsif ($cl =~ m{^(STATE_TYPE:|\@StartDeadKeyMap|\@EndDeadKeyMap)}) {
# ignore
} elsif ($cl =~ m{^include "(.*)"}) {
my $incpath = $1;
if (($pre_file == 1) && ($incpath !~ m{^X11_LOCALEDATADIR/})) {
print "Include path starts with $incpath instead of X11_LOCALEDATADIR\n",
" -- may not find include files when installed in alternate paths\n\n";
}
} else {
print 'Unrecognized pattern in ', $filename, ' on line #', $line, ":\n ",
$cl, "\n";
}
}
close $COMPOSE;
return $errors;
}
sub print_sequences {
my ($entry_ref) = @_;
if (ref($entry_ref) eq 'HASH') {
foreach my $h (values %{$entry_ref}) {
print_sequences($h);
}
} else {
my ($line, $seq) = @{$entry_ref};
print " line #", $line, ": ", $seq, "\n";
}
}