#!/usr/bin/perl ($katalog = $0) =~ s|/[^/]*$||; # Konwersja any-test wypisuje tylko oznaczenie rozpoznanego standardu zamiast # konwersji. Konwersja any-test/all wypisuje tabelkę współczynników zgodności # z poszczególnymi zestawami. if ($ARGV[0] eq "-test") {shift @ARGV; $test = 1;} # Szukamy języka w argumentach i pliku z jego opisem: foreach (split " ", $ENV{ARG}) { if ($test && $_ eq "all") {$test = 2} elsif (!$jest && open JEZYK, "$katalog/../aux/any/$_") {$jest = 1} } # Jeśli nie znaleźliśmy języka, to przepuszczamy tekst bez zmian: unless ($jest) { if ($test == 1) { print "-\n"; } elsif ($test == 2) { print "Unknown or unspecified language\n"; } else { print while <>; } exit; } # Odczytujemy dane o zestawach znaków w danym języku: while () { chomp; @znaki = split; $zestaw = shift @znaki; # '%' zamiast zestawu oznacza częstości występowania znaków: if ($zestaw eq '%') {@czestosci = @znaki} else { push @zestawy, {ZESTAW => $zestaw, ZNAKI => [@znaki]}; # Znaki zliczamy dwoma sposobami: # - Poszczególne bajty zliczamy tak czy siak, nie patrząc na # to, które są akurat potrzebne. # - Znaki dłuższe niż jeden bajt musimy zliczyć osobno. Dla # szybkości zapamiętujemy je w osobnych tablicach, względem # pierwszego bajtu. foreach (@znaki) { push @{$dlugie[ord]}, $_ if length > 1 } } } close JEZYK; unless ($test) { # Musimy przelecieć tekst dwa razy - raz, żeby zliczyć znaki, i drugi # raz, żeby go skonwertować. Podczas pierwszego przebiegu zapamiętujemy # więc test w tymczasowym pliku: open TEMP, "+>/tmp/any-$$"; unlink "/tmp/any-$$"; } # Zliczamy wystąpienia poszczególnych bajtów (w @ile) i znaków dłuższych niż # jeden bajt (w %ile): while (<>) { print TEMP $_ unless $test; chomp; my $i = 0; foreach my $znak (split //) { $ile[ord $znak]++; foreach my $znak (@{$dlugie[ord $znak]}) { $ile{$znak}++ if substr ($_, $i, length $znak) eq $znak; } } continue {$i++} } # Współczynnikiem zgodności dla danego zestawu znaków jest suma iloczynów # zaobserwowanych liczb wystąpień i średnich częstości dla danego języka # odczytanej z pliku z opisem języka: $najlepiej = 0; $najlepszy = "-"; foreach (@zestawy) { my $pasuje = 0; @znaki = @{$$_{ZNAKI}}; foreach (@czestosci) { $znak = shift @znaki; $pasuje += (length $znak > 1 ? $ile{$znak} : $ile[ord $znak]) * $_ if $znak ne "-"; } if ($test == 2) {$$_{PASUJE} = $pasuje} if ($pasuje > $najlepiej) { $najlepiej = $pasuje; $najlepszy = $$_{ZESTAW}; } } # Jeśli to był test, to tylko wypisujemy informację: if ($test == 1) { print "$najlepszy\n"; exit; } elsif ($test == 2) { foreach (sort {$$b{PASUJE} <=> $$a{PASUJE}} @zestawy) { printf "%10d: %s\n", $$_{PASUJE}, $$_{ZESTAW} if $$_{PASUJE}; } exit; } seek TEMP, 0, 0; # Jeśli z żadnego zestawu nie pasował żaden znak, to przepuszczamy plik bez # zmian: if ($najlepiej == 0) {print while ; close TEMP; exit;} ($najlepszy = "|$najlepszy-UTF8") =~ s/\|/|$katalog\//g; open WYNIK, $najlepszy; while () {print WYNIK $_} close TEMP; close WYNIK;