#!/usr/bin/perl

# Copyright (C) 2011 Morten Welinder <terra@gnome.org>
#
# 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 2 of the
# License, or (at your option) version 3.
#
# 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, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
# USA

use strict;
use Getopt::Long;
use IO::Compress::Gzip qw(gzip $GzipError);

my $myself = $0;
$myself =~ s|^.*/||;

my $WIDTH = 70;
my $regfunc = undef;
my $unregfunc = undef;
my $regfuncstatic = 0;
my $regfilefunc = "go_rsm_register_file";
my $unregfilefunc = "go_rsm_unregister_file";
my $id_prefix = "";
my @includes;

&GetOptions("register-function=s" => \$regfunc,
	    "unregister-function=s" => \$unregfunc,
	    "register-file-function=s" => \$regfilefunc,
	    "unregister-file-function=s" => \$unregfilefunc,
	    "static" => \$regfuncstatic,
	    "id-prefix=s" => \$id_prefix,
	    "include=s" => \@includes,
    ) or die "$0: invalid usage -- inquire within\n";

# -----------------------------------------------------------------------------

print "/* Generated by $myself -- do not edit! */\n\n";
foreach my $include (@includes) {
    $include = "\"$include\"" unless $include =~ /^[<""]/;
    print "#include $include\n";
}

my $fileno = 0;
my $reg = "";
my $unreg = "";
my $docompress = 0;
print "static " if $regfuncstatic;
print "void\n";
print "$regfunc (void)\n";
print "{\n";
foreach my $file (@ARGV) {
    if ($file eq 'COMPRESS') {
	$docompress = 1;
	next;
    }
    if ($file eq 'NOCOMPRESS') {
	$docompress = 0;
	next;
    }
    &embed ($file, $docompress);
}
print $reg;
print "}\n";

if (defined $unregfunc) {
    print "\n";
    print "static " if $regfuncstatic;
    print "void\n";
    print "$unregfunc (void)\n";
    print "{\n";
    print $unreg;
    print "}\n";
}

sub embed {
    my ($file, $docompress) = @_;

    print "  /* Embedded file $file */\n";

    my $data;
    {
	local (*FIL);
	local ($/);
	$/ = undef;
	open (*FIL, "<$file") or die "$myself: cannot read $file: $!\n";
	$data = <FIL>;
    }

    if ($docompress) {
	my $zdata;
	gzip \$data => \$zdata, TIME => 0,
	    or die "gzip failed: $GzipError\n";
	$data = $zdata;
    }

    my $id = "data$fileno";
    $fileno++;

    &embed_data ($data, $id);

    my $res = "$id_prefix$file";
    my $len = length ($data);
    $reg .= "  $regfilefunc (\"$res\", $id, $len);\n";
    $unreg .= "  $unregfilefunc (\"$res\");\n";
}

sub embed_data {
    my ($data,$id) = @_;

    my $len = length ($data);
    if ($len == 0) {
	print "  static const char ${id}[] = \"\";\n";
	return;
    }

    print "  static const char ${id}[] =\n";
    my $linelen = 0;
    my $nohex = 0;
    foreach my $c (split (//, $data)) {
	if ($linelen > $WIDTH) {
	    print "\"\n";
	    $linelen = 0;
	}
	if ($linelen == 0) {
	    print "    \"";
	    $linelen += 5;
	    $nohex = 0;
	} 

	my $thisnohex = $nohex;
	$nohex = 0;

	my $ci = ord ($c);
	if ($c eq "\n") {
	    print "\\n";
	    $linelen += 2;
	} elsif ($c eq "\t") {
	    print "\\t";
	    $linelen += 2;
	} elsif ($c eq '"') {
	    print "\\\"";
	    $linelen += 2;
	} elsif ($c eq "\\") {
	    print "\\\\";
	    $linelen += 2;
	} elsif ($ci >= 32 && $ci < 127) {
	    if ($thisnohex && $c =~ /[a-fA-F0-9]/) {
		print "\"\"";
		$linelen += 2;
	    }
	    print $c;
	    $linelen += 1;
	} else {
	    printf ("\\x%02x", $ci);
	    $linelen += 4;
	    $nohex = 1;
	}
    }
    print "\";\n\n";
}
