#! /usr/bin/perl -w

# Copyright (C) 2002-2012 Simon Josefsson

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

# I consider the output of this program to be unrestricted.  Use it as
# you will.

# Adapted for PHP Stringprep by Lorenz Schori <lo@znerol.ch>
# Original source: http://www.gnu.org/software/libidn/

use strict;

my ($intable) = 0;
my ($tablename);
my ($varname);
my ($profile) = "RFC3454";
my ($filename);
my ($line, $start, $end, @map);
my (%is_mapping) = ('B_2' => 1, 'B_3' => 1);

while(<>) {
    s/^   (.*)/$1/g; # for rfc
    $line = $_;

    die "already in table" if $intable && m,^----- Start Table (.*) -----,;
    die "not in table" if !$intable && m,^----- End Table (.*) -----,;

    if ($intable && m,^----- End Table (.*) -----,) {
	die "table error" unless $1 eq $tablename;
	$intable = 0;

        if ($is_mapping{$varname}) {
            print FH "    );\n";
            print FH "    return isset(\$map[\$cp]) ? \$map[\$cp] : array(\$cp);\n";
        }
        else {
            print FH "    return true;\n";
        }

	print FH "  }\n";
	print FH "}\n\n";

        close FH or die "cannot close $filename";
    }

    next unless ($intable || m,^----- Start Table (.*) -----,);

    if ($intable) {
	$_ = $line;
	chop $line;

	next if m,^$,;
	next if m,^Hoffman & Blanchet          Standards Track                    \[Page [0-9]+\]$,;
	next if m,^$,;
	next if m,RFC 3454        Preparation of Internationalized Strings   December 2002,;

	die "regexp failed on line: $line" unless
	    m,^([0-9A-F]+)(-([0-9A-F]+))?(; ([0-9A-F]+)( ([0-9A-F]+))?( ([0-9A-F]+))?( ([0-9A-F]+))?;)?,;

	die "too many mapping targets on line: $line" if $12;

	$start = $1;
	$end = $3;
	$map[0] = $5;
	$map[1] = $7;
	$map[2] = $9;
	$map[3] = $11;

	die "tables tried to map a range" if $end && $map[0];

	if ($map[3]) {
	    printf FH "      0x%06s => array(0x%06s, 0x%06s, 0x%06s, 0x%06s),\n",
	    $start, $map[0], $map[1], $map[2], $map[3];
	} elsif ($map[2]) {
	    printf FH "      0x%06s => array(0x%06s, 0x%06s, 0x%06s),\n",
	    $start, $map[0], $map[1], $map[2];
	} elsif ($map[1]) {
	    printf FH "      0x%06s => array(0x%06s, 0x%06s),\n",
	    $start, $map[0], $map[1];
	} elsif ($map[0]) {
	    printf FH "      0x%06s => array(0x%06s),\n",
	    $start, $map[0];
	} elsif ($end) {
	    printf FH "    if (\$cp >= 0x%06s && \$cp <= 0x%06s) return false;\n",
	    $start, $end;
	} else {
	    printf FH "    if (\$cp == 0x%06s) return false;\n",
	    $start;
	}
    } else {
	$intable = 1 if !$intable;
	$tablename = $1;

	($varname = $tablename) =~ tr/./_/;

        $filename = "${profile}/${varname}.php";
        open(FH, ">$filename") or die "cannot open $filename for writing";

        print FH "<?php\n";
        print FH "/* This file is automatically generated.  DO NOT EDIT!\n";
        print FH "   Instead, edit gen-stringprep-tables.pl and re-run.  */\n\n";
        print FH "namespace Znerol\\Component\\Stringprep\\RFC3454;\n";
	print FH "class ${varname} {\n";

        if ($is_mapping{$varname}) {
            print FH "  public static function map(\$cp) {\n";
            print FH "    static \$map = array(\n";
        }
        else {
            print FH "  public static function filter(\$cp) {\n";
        }
    }
}
