#!/usr/local/bin/perl
# extra options
# -DRSAref	build to use RSAref
# -DNOIDEA	build with no IDEA algorithm
# -DNORC4	build with no RC4 algorithm
#
# RSA_LLONG	use the type 'long long' in rsa/rsa.h
# MD2_CHAR	use 'char' instead of 'int' for MD2_INT in md/md2.h
# MD2_LONG	use 'long' instead of 'int' for MD2_INT in md/md2.h
# IDEA_SHORT	use 'short' instead of 'int' for IDEA_INT in idea/idea.h
# IDEA_LONG	use 'long' instead of 'int' for IDEA_INT in idea/idea.h
# RC4_CHAR	use 'char' instead of 'int' for RC4_INT in rc4/rc4.h
# RC4_LONG	use 'long' instead of 'int' for RC4_INT in rc4/rc4.h
# RC4_INDEX	define RC4_INDEX in rc4/rc4_enc.c.  This turns on
#		array lookups instead of pointer use.

#config-string	CC : CFLAGS : LDFLAGS : special header file mods
%table=(
"gcc",		"gcc:-O3 -DPROTO::RSA_LLONG",
"cc",		"cc:-O -DNOCONST::",
"hpux-cc",	"cc:+O3 -DNOCONST::",
"solaris-gcc",	"gcc:-O3 -DPROTO:-lsocket -lnsl:RSA_LLONG",
"solaris-cc",	"cc:-fast:-lsocket -lnsl:",
"sunos-cc",	"cc:-O4 -DNOCONST::",

"linux-gcc",	"gcc:-O3 -DPROTO -DTERMIO::RSA_LLONG  MD2_CHAR RC4_INDEX",
"next-gcc",	"gcc:-O3 -DPROTO::RSA_LLONG  MD2_CHAR RC4_INDEX",
"alpha-gcc",	"gcc:-O3 -DPROTO::SIXTY_FOUR_BITS ",
"alpha-cc",	"cc:-O2 -DPROTO::SIXTY_FOUR_BITS",
"irix-cc",	"cc:-O2 -DPROTO::",
"aix-cc",	"cc:-O -DPROTO::",

# don't touch
"sunos-sparc-gcc","gcc:-O3 -mv8 -DPROTO::RSA_LLONG RC4_CHAR",
"sunos-gcc",	"gcc:-O3 -DPROTO::RSA_LLONG RC4_CHAR",
"solaris-x86-gcc","gcc:-O3 -m486 -DPROTO:-lsocket -lnsl:RSA_LLONG MD2_CHAR RC4_INDEX",
"solaris-sparc-gcc","gcc:-O3 -mv8 -DPROTO:-lsocket -lnsl:RSA_LLONG RC4_CHAR",
"irix-gcc",	"gcc:-O2 -mips2 -DPROTO::RSA_LLONG RC4_INDEX RC4_CHAR",
"dgux-gcc",	"gcc:-O3 -DPROTO::RC4_INDEX",
"hpux-gcc",	"gcc:-O3 -mpa-risc-1-1 -DPROTO::RSA_LLONG",
);

$Makefile="Makefile";
$bn	="rsa/bn.h";
$md2	="md/md2.h";
$rc4	="rc4/rc4.h";
$rc4_enc="rc4/rc4_enc.c";
$idea	="idea/idea.h";

if ($#ARGV < 0)
	{
	&bad_target;
	exit(1);
	}

$flags="";
foreach (@ARGV)
	{
	if ($_ =~ /^-/)
		{ $flags.=$_." "; }
	else
		{
		die "target already defined - $target\n" if ($target ne "");
		$target=$_;
		if (!defined($table{$target}))
			{
			&bad_target;
			exit(1);
			}
		}
	}

if (!defined($table{$target}))
	{
	&bad_target;
	exit(1);
	}

($cc,$cflags,$lflags,$bn_ops)=split(/:/,$table{$target});
$cflags=$flags if ($flags ne "");

open(IN,"<".$Makefile) || die "unable to read $Makefile:$!\n";
open(OUT,">".$Makefile.".new") || die "unable to read $Makefile.new:$!\n";
while (<IN>)
	{
	chop;
	s/^CC=.*$/CC= $cc/;
	s/^CFLAG=.*$/CFLAG= $cflags/;
	s/^EX_LIBS=.*$/EX_LIBS= $lflags/;
	print OUT $_."\n";
	}
close(IN);
close(OUT);
rename($Makefile,$Makefile.".old");
rename($Makefile.".new",$Makefile);
print "CC=$cc\n";
print "CFLAG=$cflags\n";
print "EX_LIBS=$lflags\n";

$rsa_ll=0;
$def_int=2;
$rc4_int=$def_int;
$md2_int=$def_int;
$idea_int=$def_int;
$rc4_idx=0;
@type=("char","short","int","long");
($b64,$b32,$b16)=(0,1,0);

foreach (split(/\s+/,$bn_ops))
	{
	$rsa_ll=1 if /RSA_LLONG/;
	$rc4_int=0 if /RC4_CHAR/;
	$rc4_int=3 if /RC4_LONG/;
	$rc4_idx=1 if /RC4_INDEX/;
	$md2_int=0 if /MD2_CHAR/;
	$md2_int=3 if /MD2_LONG/;
	$idea_int=1 if /IDEA_SHORT/;
	$idea_int=3 if /IDEA_LONG/;

	($b64,$b32,$b16)=(1,0,0) if /SIXTY_FOUR_BITS/;
	($b64,$b32,$b16)=(0,1,0) if /THIRTY_TWO_BITS/;
	($b64,$b32,$b16)=(0,0,1) if /SIXTEEN_BITS/;
	}

open(IN,"<".$bn) || die "unable to read $bn:$!\n";
open(OUT,">".$bn.".new") || die "unable to read $bn.new:$!\n";
while (<IN>)
	{
	if	(/^#((define)|(undef))\s+SIXTY_FOUR_BIT/)
		{ printf OUT "#%s SIXTY_FOUR_BIT\n",($b64)?"define":"undef"; }
	elsif	(/^#((define)|(undef))\s+THIRTY_TWO_BIT/)
		{ printf OUT "#%s THIRTY_TWO_BIT\n",($b32)?"define":"undef"; }
	elsif	(/^#((define)|(undef))\s+SIXTEEN_BIT/)
		{ printf OUT "#%s SIXTEEN_BIT\n",($b16)?"define":"undef"; }
	elsif	(/^#((define)|(undef))\s+RSA_LLONG/)
		{ printf OUT "#%s RSA_LLONG\n",($rsa_ll)?"define":"undef"; }
	else
		{ print OUT $_; }
	}
close(IN);
close(OUT);
rename($bn,$bn.".old");
rename($bn.".new",$bn);

open(IN,"<".$rc4) || die "unable to read $rc4:$!\n";
open(OUT,">".$rc4.".new") || die "unable to read $rc4.new:$!\n";
while (<IN>)
	{
	if	(/^#define\s+RC4_INT\s/)
		{ printf OUT "#define RC4_INT unsigned %s\n",$type[$rc4_int]; }
	else
		{ print OUT $_; }
	}
close(IN);
close(OUT);
rename($rc4,$rc4.".old");
rename($rc4.".new",$rc4);

open(IN,"<".$rc4_enc) || die "unable to read $rc4_enc:$!\n";
open(OUT,">".$rc4_enc.".new") || die "unable to read $rc4_enc.new:$!\n";
while (<IN>)
	{
	if	(/^#((define)|(undef))\s+RC4_INDEX/)
		{ printf OUT "#%s RC4_INDEX\n",($rc4_idx)?"define":"undef"; }
	else
		{ print OUT $_; }
	}
close(IN);
close(OUT);
rename($rc4_enc,$rc4_enc.".old");
rename($rc4_enc.".new",$rc4_enc);

open(IN,"<".$md2) || die "unable to read $bn:$!\n";
open(OUT,">".$md2.".new") || die "unable to read $bn.new:$!\n";
while (<IN>)
	{
	if	(/^#define\s+MD2_INT\s/)
		{ printf OUT "#define MD2_INT unsigned %s\n",$type[$md2_int]; }
	else
		{ print OUT $_; }
	}
close(IN);
close(OUT);
rename($md2,$md2.".old");
rename($md2.".new",$md2);

open(IN,"<".$idea) || die "unable to read $idea:$!\n";
open(OUT,">".$idea.".new") || die "unable to read $idea.new:$!\n";
while (<IN>)
	{
	if	(/^#define\s+IDEA_INT\s/)
		{printf OUT "#define IDEA_INT unsigned %s\n",$type[$idea_int];}
	else
		{ print OUT $_; }
	}
close(IN);
close(OUT);
rename($idea,$idea.".old");
rename($idea.".new",$idea);

print "SIXTY_FOUR_BIT mode\n" if $b64;
print "THIRTY_TWO_BIT mode\n" if $b32;
print "SIXTEEN_BIT mode\n" if $b16;
print "RSA_LLONG mode\n" if $rsa_ll;
print "RC4 uses u$type[$rc4_int]\n" if $rc4_int != $def_int;
print "RC4_INDEX mode\n" if $rc4_idx;
print "MD2 uses u$type[$md2_int]\n" if $md2_int != $def_int;
print "IDEA uses u$type[$idea_int]\n" if $idea_int != $def_int;
exit(0);

sub bad_target
	{
	print STDERR "bad target OS-compiler; pick one of:\n";
	$j=0;
	foreach $i (sort keys %table)
		{
		print STDERR "\n" if ($j++ % 4) == 0;
		printf(STDERR "%-19s ",$i);
		}
	print STDERR "\n";
	}




