#!/usr/bin/perl
use strict;
require 'uricls.pl';
our $LIST;
my %argv;
for (@ARGV) {
$argv{$1} = 1 if /^--([^\s=]+)$/;
}
if ($argv{help}) {
require Pod::Usage;
Pod::Usage::pod2usage (-exitval => 0, -verbose => 1);
}
sub add (%) {
my (%opt) = @_;
push @{$opt{table}->[0]}, $opt{name};
push @{$opt{table}->[$_]}, [] for 1..$#{$opt{table}};
for my $class (sort keys %{$opt{list}}) {
ELEMENT: for my $element (@{$opt{list}->{$class}}) {
for (@{$opt{table}}) {
if ($_->[0] eq $element) {
push @{$_->[-1]}, $class;
next ELEMENT;
}
}
my $row = [$element];
for (my $i = $#{$opt{table}->[0]} - 1; $i > 0; $i--) {
push @$row, [];
}
push @$row, [$class];
push @{$opt{table}}, $row;
}
}
}
sub element ($) {
my $el = shift;
if (length $el > 1 || $el =~ /[A-Z%]/) {
qq<$el
>;
} else {
qq<$el
>;
}
}
sub elements ($) {
join ', ', map {element $_} @{$_[0]};
}
sub serialize ($$) {
my ($tbl, $span) = @_;
my $r = q<
>;
$r .= join '', map {qq<$_ | >} @{$tbl->[0]};
$r .= q<
>;
for my $i (1..$#$tbl) {
$r .= q<>;
$r .= q<>.element ($tbl->[$i]->[0]).q< | >;
for my $j (1..$#{$tbl->[$i]}) {
if ($tbl->[$i]->[$j]) {
$r .= q{ if $span->[$i]->[$j]->{row};
$r .= q< colspan=">.$span->[$i]->[$j]->{col}.q<"> if $span->[$i]->[$j]->{col};
$r .= q{>};
$r .= elements ($tbl->[$i]->[$j]) || '-';
$r .= q< | >;
}
}
$r .= qq<
\n>;
}
$r .= qq<
\n>;
$r;
}
sub equal ($$) {
my ($x, $y) = @_;
return 0 unless @$x and @$y;
return 0 unless @$x == @$y;
for (0..$#$x) {
return 0 unless $x->[$_] eq $y->[$_];
}
return 1;
}
sub merge_row ($$) {
my ($tbl, $span) = @_;
for my $i (1..($#$tbl-1)) {
for my $j (1..$#{$tbl->[$i]}) {
if ($tbl->[$i]->[$j]) {
my $s = 1;
for my $ii (($i+1)..$#$tbl) {
if (equal $tbl->[$i]->[$j] => $tbl->[$ii]->[$j]) {
$s++;
$tbl->[$ii]->[$j] = 0;
} else {
last;
}
}
$span->[$i]->[$j]->{row} = $s if $s > 1;
}
}
}
}
sub merge_col ($$) {
my ($tbl, $span) = @_;
for my $i (1..$#$tbl) {
for my $j (1..($#{$tbl->[$i]}-1)) {
if ($tbl->[$i]->[$j]) {
my $s = 1;
for my $jj (($j+1)..$#{$tbl->[$i]}) {
if ($tbl->[$i]->[$jj] and
$span->[$i]->[$j]->{row} == $span->[$i]->[$jj]->{row} and
equal $tbl->[$i]->[$j] => $tbl->[$i]->[$jj]) {
$s++;
$tbl->[$i]->[$jj] = 0;
} else {
last;
}
}
$span->[$i]->[$j]->{col} = $s if $s > 1;
}
}
}
}
sub remove_empty_row ($) {
my @tbl = @{+shift};
ROW: for (my $i = $#tbl; $i > 1; $i--) {
for my $j (1..$#{$tbl[$i]}) {
next ROW if not $tbl[$i]->[$j] or
@{$tbl[$i]->[$j]};
}
delete $tbl[$i];
}
[grep defined $_, @tbl];
}
my $tbl = [map {[$_]} '', qw >, 'SP', '%x00-1F', '%x7F'];
my @span;
for (@$LIST) {
add table => $tbl, name => $_->{name}, list => $_->{class};
}
$tbl = remove_empty_row $tbl;
merge_row $tbl, \@span;
merge_col $tbl, \@span;
print STDOUT qq<\n>;
print STDOUT serialize $tbl, \@span;
=head1 NAME
mkclstbl - URI Character Class History Table Generator
=head1 SYNOPSIS
mkclstbl.pl > table.html
mkclstbl.pl --help
=head1 DESCRIPTION
This script generates an HTML table that describes what character belongs
to what character class(es) in versions of URI specification.
=head1 OPTIONS
This script can be specified an arguments:
=over 4
=item --help
Show help message.
=back
=head1 SEE ALSO
URI Specifications and DTDs.
.
=head1 LICENSE
Copyright 2004 Wakaba
This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.
=cut
# $Date: 2010/06/18 14:23:05 $