#! /usr/local/bin/perl -w

use strict;

my @charsets = (
  { name => "Latin-1", file => "iso-8859-1.txt", abbr => "1",
    descr => "Latin-1 (ISO-8859-1: Western European)" },
  { name => "Latin-2", file => "iso-8859-2.txt", abbr => "2",
    descr => "Latin-2 (ISO-8859-2: Central European)" },
  { name => "Latin-3", file => "iso-8859-3.txt", abbr => "3",
    descr => "Latin-3 (ISO-8859-3: South European and Esperanto)" },
  { name => "Latin-4", file => "iso-8859-4.txt", abbr => "4",
    descr => "Latin-4 (ISO-8859-4: Baltic, old)" },
  { name => "Cyrillic", file => "iso-8859-5.txt", abbr => "C",
    descr => "Cyrillic (ISO-8859-5)" },
  { name => "Arabic", file => "iso-8859-6.txt", abbr => "A",
    descr => "Arabic (ISO-8859-6)" },
  { name => "Greek", file => "iso-8859-7.txt", abbr => "G",
    descr => "Greek (ISO-8859-7)" },
  { name => "Hebrew", file => "iso-8859-8.txt", abbr => "H",
    descr => "Hebrew (ISO-8859-8)" },
  { name => "Latin-5", file => "iso-8859-9.txt", abbr => "5",
    descr => "Latin-5 (ISO-8859-9: Turkish)" },
  { name => "Latin-6", file => "iso-8859-10.txt", abbr => "6",
    descr => "Latin-6 (ISO-8859-10: Nordic)" },
  { name => "Thai", file => "iso-8859-11.txt", abbr => "T",
    descr => "Thai (ISO-8859-11, unofficial)" },
  { name => "Latin-7", file => "iso-8859-13.txt", abbr => "7",
    descr => "Latin-7 (ISO-8859-13: Baltic, new)" },
  { name => "Latin-8", file => "iso-8859-14.txt", abbr => "8",
    descr => "Latin-8 (ISO-8859-14: Celtic)" },
  { name => "Latin-9", file => "iso-8859-15.txt", abbr => "9",
    descr => "Latin-9 (ISO-8859-15: Revised Western European)" },
  { name => "DEC-MCS", file => "dec-mcs.txt", abbr => "D",
    descr => "<abbr>DEC</abbr> Multilingual Character Set" },
  { name => "CP1252", file => "cp1252.txt", abbr => "w",
    descr => "Codepage 1252 (Microsoft Windows Western European)" },
  { name => "CP1250", file => "cp1250.txt", abbr => "w2",
    descr => "Codepage 1250 (Microsoft Windows Central European)" },
  { name => "CP1251", file => "cp1251.txt", abbr => "wC",
    descr => "Codepage 1251 (Microsoft Windows Cyrillic)" },
  { name => "CP1253", file => "cp1253.txt", abbr => "wG",
    descr => "Codepage 1253 (Microsoft Windows Greek)" },
  { name => "CP1254", file => "cp1254.txt", abbr => "w5",
    descr => "Codepage 1254 (Microsoft Windows Turkish)" },
  { name => "CP1255", file => "cp1255.txt", abbr => "wH",
    descr => "Codepage 1255 (Microsoft Windows Hebrew)" },
  { name => "CP1256", file => "cp1256.txt", abbr => "wA",
    descr => "Codepage 1256 (Microsoft Windows Arabic)" },
  { name => "CP1257", file => "cp1257.txt", abbr => "w7",
    descr => "Codepage 1257 (Microsoft Windows Baltic)" },
  { name => "CP1258", file => "cp1258.txt", abbr => "wv",
    descr => "Codepage 1258 (Microsoft Windows Vietnamese)" },
  { name => "IBM-PC", file => "ibmpc.txt", abbr => "V",
    descr => "<abbr>VGA</abbr> codepage 437 (<abbr>VGA</abbr> <abbr>ROM</abbr> charset)" },
  { name => "CP437", file => "cp437.txt", abbr => "*",
    descr => "Codepage 437 (<abbr>IBM</abbr>-<abbr>PC</abbr>: default)" },
  { name => "CP737", file => "cp737.txt", abbr => "*G",
    descr => "Codepage 737 (<abbr>IBM</abbr>-<abbr>PC</abbr>: Greek)" },
  { name => "CP775", file => "cp775.txt", abbr => "*b",
    descr => "Codepage 775 (<abbr>IBM</abbr>-<abbr>PC</abbr>: Baltic)" },
  { name => "CP850", file => "cp850.txt", abbr => "*w",
    descr => "Codepage 850 (<abbr>IBM</abbr>-<abbr>PC</abbr>: European)" },
  { name => "CP852", file => "cp852.txt", abbr => "*e",
    descr => "Codepage 852 (<abbr>IBM</abbr>-<abbr>PC</abbr>: East European)" },
  { name => "CP855", file => "cp855.txt", abbr => "*C",
    descr => "Codepage 855 (<abbr>IBM</abbr>-<abbr>PC</abbr>: Cyrillic)" },
  { name => "CP857", file => "cp857.txt", abbr => "*t",
    descr => "Codepage 857 (<abbr>IBM</abbr>-<abbr>PC</abbr>: Turkish)" },
  { name => "CP860", file => "cp860.txt", abbr => "*p",
    descr => "Codepage 860 (<abbr>IBM</abbr>-<abbr>PC</abbr>: Portuguese)" },
  { name => "CP861", file => "cp861.txt", abbr => "*i",
    descr => "Codepage 861 (<abbr>IBM</abbr>-<abbr>PC</abbr>: Icelandic)" },
  { name => "CP862", file => "cp862.txt", abbr => "*H",
    descr => "Codepage 862 (<abbr>IBM</abbr>-<abbr>PC</abbr>: Hebrew)" },
  { name => "CP863", file => "cp863.txt", abbr => "*q",
    descr => "Codepage 863 (<abbr>IBM</abbr>-<abbr>PC</abbr>: Canadian French)" },
  { name => "CP864", file => "cp864.txt", abbr => "*A",
    descr => "Codepage 864 (<abbr>IBM</abbr>-<abbr>PC</abbr>: Arabic)" },
  { name => "CP865", file => "cp865.txt", abbr => "*n",
    descr => "Codepage 865 (<abbr>IBM</abbr>-<abbr>PC</abbr>: Nordic European)" },
  { name => "CP866", file => "cp866.txt", abbr => "*C2",
    descr => "Codepage 866 (<abbr>IBM</abbr>-<abbr>PC</abbr>: Cyrillic 2)" },
  { name => "CP869", file => "cp869.txt", abbr => "*G2",
    descr => "Codepage 869 (<abbr>IBM</abbr>-<abbr>PC</abbr>: Greek 2)" },
  { name => "CP874", file => "cp874.txt", abbr => "*T",
    descr => "Codepage 874 (<abbr>IBM</abbr>-<abbr>PC</abbr> / Microsoft Windows: Thai)" },
  { name => "Mac-Roman", file => "mac-roman.txt", abbr => "M",
    descr => "Macintosh Roman" },
  { name => "Mac-Icelandic", file => "mac-iceland.txt", abbr => "Mi",
    descr => "Macintosh Icelandic" },
  { name => "Mac-Turkish", file => "mac-turkish.txt", abbr => "Mt",
    descr => "Macintosh Turkish" },
  { name => "Mac-Central-European", file => "mac-centeuro.txt", abbr => "Me",
    descr => "Macintosh Central European" },
  { name => "Mac-Croatian", file => "mac-croatian.txt", abbr => "Mc",
    descr => "Macintosh Croatian" },
  { name => "Mac-Romanian", file => "mac-romanian.txt", abbr => "Mr",
    descr => "Macintosh Romanian" },
  { name => "Mac-Cyrillic", file => "mac-cyrillic.txt", abbr => "MC",
    descr => "Macintosh Cyrillic" },
  { name => "Mac-Arabic", file => "mac-arabic.txt", abbr => "MA",
    descr => "Macintosh Arabic" },
  { name => "Mac-Farsi", file => "mac-farsi.txt", abbr => "MAF",
    descr => "Macintosh Arabic (Farsi)" },
  { name => "Mac-Greek", file => "mac-greek.txt", abbr => "MG",
    descr => "Macintosh Greek" },
  { name => "Mac-Hebrew", file => "mac-hebrew.txt", abbr => "MH",
    descr => "Macintosh Hebrew" },
  { name => "Mac-Thai", file => "mac-thai.txt", abbr => "MT",
    descr => "Macintosh Thai" },
  { name => "Mac-Devanagari", file => "mac-devanaga.txt", abbr => "MDev",
    descr => "Macintosh Devanagari" },
  { name => "Mac-Gujarati", file => "mac-gujarati.txt", abbr => "MGuj",
    descr => "Macintosh Gujarati" },
  { name => "Mac-Gurmukhi", file => "mac-gurmukhi.txt", abbr => "MGur",
    descr => "Macintosh Gurmukhi" },
  { name => "Mac-Symbol", file => "mac-symbol.txt", abbr => "MS",
    descr => "Macintosh Symbol" },
  { name => "Mac-Dingbats", file => "mac-dingbats.txt", abbr => "MSD",
    descr => "Macintosh Dingbats" },
  { name => "KOI8-R", file => "koi8-r.txt", abbr => "kC",
    descr => "KOI8-R (<abbr>RFC</abbr> 1489)" },
  { name => "KOI8-U", file => "koi8-u.txt", abbr => "kCU",
    descr => "KOI8-U (<abbr>RFC</abbr> 2319)" },
  { name => "PS-Standard", file => "ps-standard.txt", abbr => "p!",
    descr => "PostScript StandardEncoding" },
  { name => "PS-Latin1", file => "ps-latin1.txt", abbr => "p1",
    descr => "PostScript ISOLatin1Encoding" },
  { name => "PS-Symbol", file => "ps-symbol.txt", abbr => "pS",
    descr => "PostScript Symbol" },
);

my %htmlentities = (
  160=>"nbsp",  161=>"iexcl",  162=>"cent",  163=>"pound",
  164=>"curren",  165=>"yen",  166=>"brvbar",  167=>"sect",
  168=>"uml",  169=>"copy",  170=>"ordf",  171=>"laquo",
  172=>"not",  173=>"shy",  174=>"reg",  175=>"macr",
  176=>"deg",  177=>"plusmn",  178=>"sup2",  179=>"sup3",
  180=>"acute",  181=>"micro",  182=>"para",  183=>"middot",
  184=>"cedil",  185=>"sup1",  186=>"ordm",  187=>"raquo",
  188=>"frac14",  189=>"frac12",  190=>"frac34",  191=>"iquest",
  192=>"Agrave",  193=>"Aacute",  194=>"Acirc",  195=>"Atilde",
  196=>"Auml",  197=>"Aring",  198=>"AElig",  199=>"Ccedil",
  200=>"Egrave",  201=>"Eacute",  202=>"Ecirc",  203=>"Euml",
  204=>"Igrave",  205=>"Iacute",  206=>"Icirc",  207=>"Iuml",
  208=>"ETH",  209=>"Ntilde",  210=>"Ograve",  211=>"Oacute",
  212=>"Ocirc",  213=>"Otilde",  214=>"Ouml",  215=>"times",
  216=>"Oslash",  217=>"Ugrave",  218=>"Uacute",  219=>"Ucirc",
  220=>"Uuml",  221=>"Yacute",  222=>"THORN",  223=>"szlig",
  224=>"agrave",  225=>"aacute",  226=>"acirc",  227=>"atilde",
  228=>"auml",  229=>"aring",  230=>"aelig",  231=>"ccedil",
  232=>"egrave",  233=>"eacute",  234=>"ecirc",  235=>"euml",
  236=>"igrave",  237=>"iacute",  238=>"icirc",  239=>"iuml",
  240=>"eth",  241=>"ntilde",  242=>"ograve",  243=>"oacute",
  244=>"ocirc",  245=>"otilde",  246=>"ouml",  247=>"divide",
  248=>"oslash",  249=>"ugrave",  250=>"uacute",  251=>"ucirc",
  252=>"uuml",  253=>"yacute",  254=>"thorn",  255=>"yuml",
  338=>"OElig",  339=>"oelig",  352=>"Scaron",  353=>"scaron",
  376=>"Yuml",  710=>"circ",  732=>"tilde",  8194=>"ensp",
  8195=>"emsp",  8201=>"thinsp",  8204=>"zwnj",  8205=>"zwj",
  8206=>"lrm",  8207=>"rlm",  8211=>"ndash",  8212=>"mdash",
  8216=>"lsquo",  8217=>"rsquo",  8218=>"sbquo",  8220=>"ldquo",
  8221=>"rdquo",  8222=>"bdquo",  8224=>"dagger",  8225=>"Dagger",
  8240=>"permil",  8249=>"lsaquo",  8250=>"rsaquo",  8364=>"euro",
  402=>"fnof",  913=>"Alpha",  914=>"Beta",  915=>"Gamma",
  916=>"Delta",  917=>"Epsilon",  918=>"Zeta",  919=>"Eta",
  920=>"Theta",  921=>"Iota",  922=>"Kappa",  923=>"Lambda",
  924=>"Mu",  925=>"Nu",  926=>"Xi",  927=>"Omicron",
  928=>"Pi",  929=>"Rho",  931=>"Sigma",  932=>"Tau",
  933=>"Upsilon",  934=>"Phi",  935=>"Chi",  936=>"Psi",
  937=>"Omega",  945=>"alpha",  946=>"beta",  947=>"gamma",
  948=>"delta",  949=>"epsilon",  950=>"zeta",  951=>"eta",
  952=>"theta",  953=>"iota",  954=>"kappa",  955=>"lambda",
  956=>"mu",  957=>"nu",  958=>"xi",  959=>"omicron",
  960=>"pi",  961=>"rho",  962=>"sigmaf",  963=>"sigma",
  964=>"tau",  965=>"upsilon",  966=>"phi",  967=>"chi",
  968=>"psi",  969=>"omega",  977=>"thetasym",  978=>"upsih",
  982=>"piv",  8226=>"bull",  8230=>"hellip",  8242=>"prime",
  8243=>"Prime",  8254=>"oline",  8260=>"frasl",  8472=>"weierp",
  8465=>"image",  8476=>"real",  8482=>"trade",  8501=>"alefsym",
  8592=>"larr",  8593=>"uarr",  8594=>"rarr",  8595=>"darr",
  8596=>"harr",  8629=>"crarr",  8656=>"lArr",  8657=>"uArr",
  8658=>"rArr",  8659=>"dArr",  8660=>"hArr",  8704=>"forall",
  8706=>"part",  8707=>"exist",  8709=>"empty",  8711=>"nabla",
  8712=>"isin",  8713=>"notin",  8715=>"ni",  8719=>"prod",
  8721=>"sum",  8722=>"minus",  8727=>"lowast",  8730=>"radic",
  8733=>"prop",  8734=>"infin",  8736=>"ang",  8743=>"and",
  8744=>"or",  8745=>"cap",  8746=>"cup",  8747=>"int",
  8756=>"there4",  8764=>"sim",  8773=>"cong",  8776=>"asymp",
  8800=>"ne",  8801=>"equiv",  8804=>"le",  8805=>"ge",
  8834=>"sub",  8835=>"sup",  8836=>"nsub",  8838=>"sube",
  8839=>"supe",  8853=>"oplus",  8855=>"otimes",  8869=>"perp",
  8901=>"sdot",  8968=>"lceil",  8969=>"rceil",  8970=>"lfloor",
  8971=>"rfloor",  9001=>"lang",  9002=>"rang",  9674=>"loz",
  9824=>"spades",  9827=>"clubs",  9829=>"hearts",  9830=>"diams",
);

my %ctlname = (
  0=>"nul", 1=>"stx", 2=>"sot", 3=>"etx",
  4=>"eot", 5=>"enq", 6=>"ack", 7=>"bel",
  8=>"bs", 9=>"ht", 10=>"lf", 11=>"vt",
  12=>"ff", 13=>"cr", 14=>"so", 15=>"si",
  16=>"dle", 17=>"dc1", 18=>"dc2", 19=>"dc3",
  20=>"dc4", 21=>"nak", 22=>"syn", 23=>"etb",
  24=>"can", 25=>"em", 26=>"sub", 27=>"esc",
  28=>"fs", 29=>"gs", 30=>"rs", 31=>"us",
  127=>"del",
  128=>"pad", 129=>"hop", 130=>"bph", 131=>"nbh",
  132=>"ind", 133=>"nel", 134=>"ssa", 135=>"esa",
  136=>"hts", 137=>"htj", 138=>"vts", 139=>"pld",
  140=>"plu", 141=>"ri", 142=>"ss2", 143=>"ss3",
  144=>"dcs", 145=>"pu1", 146=>"pu2", 147=>"sts",
  148=>"cch", 149=>"mw", 150=>"spa", 151=>"epa",
  152=>"sos", 153=>"sgci", 154=>"sci", 155=>"csi",
  156=>"st", 157=>"osc", 158=>"pm", 159=>"apc",
);

my %uni_names;

open F, "< UnicodeData-3.0.0.txt";
while ( <F> ) {
    die "Badly formed Unicode data"
	unless /^([0-9A-F]{4})\;(.*?)\;/;
    my $chr = hex($1);
    $uni_names{$chr} = $2;
}
close F;

my %csdata;

my ($csr, $cs);

foreach $csr ( @charsets ) {
    $cs = $csr->{name};
    my $fn = $csr->{file};
    open F, "< $fn";
    while ( <F> ) {
	die "Badly formed line"
	    unless /^(0+|0x[0-9a-f]+)\s+(0+|0x[0-9a-f]+)$/;
	my $num = hex($1);  my $val = hex($2);
	$csdata{$cs}[$num] = $val;
    }
    close F;
}

sub doletter {
    my $csr = shift;  my $cs = $csr->{name};
    my $num = shift;
    my $chr = $csdata{$cs}[$num];
    unless (defined($chr)) {
	return "<span class=\"ctlcode\">XX</span>";
    }
    if ( $chr < 32 || $chr >= 128 && $chr < 160 || $chr == 127 ) {
	return "<span class=\"ctlcode\">$ctlname{$chr}</span>";
    }
    return "<span class=\"ctlcode\">sp</span>" if $chr == 32;
    return "<span class=\"ctlcode\">nbsp</span>" if $chr == 160;
    return "<span class=\"ctlcode\">shy</span>" if $chr == 173;
    return "&quot;" if $chr == 34;
    return "&amp;" if $chr == 38;
    return "&lt;" if $chr == 60;
    return "&gt;" if $chr == 62;
    return "&apos;" if $chr == 39;
    return chr($chr) if $chr < 128;
    if ( $chr == 63743 && $cs =~ /^Mac-/ ) {
	return "<span class=\"ctlcode\">logo</span>";
    } elsif ( $chr == 63648 && $cs =~ /^Mac-/ ) {
	return "<span class=\"ctlcode\">XX</span>";
    } elsif ( $chr == 63594 && $cs =~ /^Mac-/ ) {
	return "<span class=\"ctlcode\">lig</span>";
    } elsif ( $chr >= 63717 && $chr <= 63719 && $cs =~ /^Mac-/ ) {
	return "<span class=\"ctlcode\">sym</span>";
    } elsif ( $chr == 63732 && $cs =~ /^Mac-/ ) {
	return "<span class=\"ctlcode\">sym</span>";
    } elsif ( $chr >= 63643 && $chr <= 63646 && $cs eq "Mac-Hebrew" ) {
	return "<span class=\"ctlcode\">obs</span>";
    }
    if ( $chr == 65533 && $cs eq "PS-Symbol" ) {
	return "<span class=\"ctlcode\">elt</span>";
    }
    unless (defined($uni_names{$chr})) {
	print STDERR "Warning: character $chr not in Unicode tables";
	print STDERR " (charset $cs)\n";
	return "<span class=\"ctlcode\">??</span>";
    }
    if (defined($htmlentities{$chr})) {
	return "&$htmlentities{$chr};";
    } else {
	return "&#$chr;";
    }
}

print << '__EOF__';
<?xml version="1.0" encoding="us-ascii"?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">


<head>

<title>Tables of Common Character Sets</title>

<meta name="description" content="The tables of various common character sets in relation to Unicode" lang="en" />

<meta name="keywords" content="Unicode, HTML, internationalization, i18n, character set, ISO-10646-1, ISO-8859" lang="en" />

<meta http-equiv="Content-Type" content="text/html; charset=us-ascii" />

<meta http-equiv="Content-Language" content="en" />

<style type="text/css">
.ctlcode { font-size: 60% }
@media screen { .ctlcode { color: red } }
</style>

</head>


<body>


<h1>Tables of Common Character Sets</h1>


<h2>Summary</h2>

<p>This page gives the tables of a few common character sets.  The
various cells contain the Unicode character that represents the
character set&apos;s entry.</p>


__EOF__

print "<h2>List of character sets</h2>\n\n<ul>\n";
foreach $csr ( @charsets ) {
    print "<li>";
    print "<a href=\"#$csr->{name}\">$csr->{descr}</a>";
    print "</li>\n";
}
print "</ul>\n\n\n";

foreach $csr ( @charsets ) {
    my ($i, $j);
    print "<h2 id=\"$csr->{name}\"><a name=\"$csr->{name}\">";
    print "$csr->{descr}</a></h2>\n\n";
    print "<table border=\"1\">\n";
    print "<tr>\n";
    print "<th>$csr->{abbr}</th>\n";
    for ( $j=0 ; $j<16 ; $j++ ) {
	printf "<th>%x</th>", $j;
    }
    print "</tr>\n";
    for ( $i=0 ; $i<16 ; $i++ ) {
	print "<tr>\n";
	printf "<th>0x%x</th>", $i;
	for ( $j=0 ; $j<16 ; $j++ ) {
	    print "<td>";
	    print (doletter($csr,(($i<<4)|$j)));
	    print "</td>";
	    print "\n" if ( ($j&3)==3 );
	}
	print "</tr>\n";
    }
    print "</table>\n\n\n";
}

print "</body>\n</html>\n";
