#!/usr/bin/env perl

# fixes bug in floating point emulation on sparc64 when
# this script produces off-by-one output on sparc64
use integer;

if (scalar @ARGV != 2)
	{
	print "Usage: perl obj_dat.pl ../../include/openssl/obj_mac.h obj_dat.h\n";
	exit 1;
	}

sub obj_cmp
	{
	local(@a,@b,$_,$r);

	$A=$obj_len{$obj{$nid{$a}}};
	$B=$obj_len{$obj{$nid{$b}}};

	$r=($A-$B);
	return($r) if $r != 0;

	$A=$obj_der{$obj{$nid{$a}}};
	$B=$obj_der{$obj{$nid{$b}}};

	return($A cmp $B);
	}

sub expand_obj
	{
	local(*v)=@_;
	local($k,$d);
	local($i);

	do	{
		$i=0;
		foreach $k (keys %v)
			{
			if (($v{$k} =~ s/(OBJ_[^,]+),/$v{$1},/))
				{ $i++; }
			}
		} while($i);
	foreach $k (keys %v)
		{
		@a=split(/,/,$v{$k});
		$objn{$k}=$#a+1;
		}
	return(%objn);
	}

open (IN,"$ARGV[0]") || die "Can't open input file $ARGV[0]";
open (OUT,">$ARGV[1]") || die "Can't open output file $ARGV[1]";

while (<IN>)
	{
	next unless /^\#define\s+(\S+)\s+(.*)$/;
	$v=$1;
	$d=$2;
	$d =~ s/^\"//;
	$d =~ s/\"$//;
	if ($v =~ /^SN_(.*)$/)
		{
		if(defined $snames{$d})
			{
			print "WARNING: Duplicate short name \"$d\"\n";
			}
		else 
			{ $snames{$d} = "X"; }
		$sn{$1}=$d;
		}
	elsif ($v =~ /^LN_(.*)$/)
		{
		if(defined $lnames{$d})
			{
			print "WARNING: Duplicate long name \"$d\"\n";
			}
		else 
			{ $lnames{$d} = "X"; }
		$ln{$1}=$d;
		}
	elsif ($v =~ /^NID_(.*)$/)
		{ $nid{$d}=$1; }
	elsif ($v =~ /^OBJ_(.*)$/)
		{
		$obj{$1}=$v;
		$objd{$v}=$d;
		}
	}
close IN;

%ob=&expand_obj(*objd);

@a=sort { $a <=> $b } keys %nid;
$n=$a[$#a]+1;

@lvalues=();
$lvalues=0;

for ($i=0; $i<$n; $i++)
	{
	if (!defined($nid{$i}))
		{
		push(@out,"{NULL,NULL,NID_undef,0,NULL,0},\n");
		}
	else
		{
		$sn=defined($sn{$nid{$i}})?"$sn{$nid{$i}}":"NULL";
		$ln=defined($ln{$nid{$i}})?"$ln{$nid{$i}}":"NULL";

		if ($sn eq "NULL") {
			$sn=$ln;
			$sn{$nid{$i}} = $ln;
		}

		if ($ln eq "NULL") {
			$ln=$sn;
			$ln{$nid{$i}} = $sn;
		}
			
		$out ="{";
		$out.="\"$sn\"";
		$out.=","."\"$ln\"";
		$out.=",NID_$nid{$i},";
		if (defined($obj{$nid{$i}}) && $objd{$obj{$nid{$i}}} =~ /,/)
			{
			$v=$objd{$obj{$nid{$i}}};
			$v =~ s/L//g;
			$v =~ s/,/ /g;
			$r=&der_it($v);
			$z="";
			$length=0;
			foreach (unpack("C*",$r))
				{
				$z.=sprintf("0x%02X,",$_);
				$length++;
				}
			$obj_der{$obj{$nid{$i}}}=$z;
			$obj_len{$obj{$nid{$i}}}=$length;

			push(@lvalues,sprintf("%-45s/* [%3d] %s */\n",
				$z,$lvalues,$obj{$nid{$i}}));
			$out.="$length,&(lvalues[$lvalues]),0";
			$lvalues+=$length;
			}
		else
			{
			$out.="0,NULL,0";
			}
		$out.="},\n";
		push(@out,$out);
		}
	}

@a=grep(defined($sn{$nid{$_}}),0 .. $n);
foreach (sort { $sn{$nid{$a}} cmp $sn{$nid{$b}} } @a)
	{
	push(@sn,sprintf("%2d,\t/* \"$sn{$nid{$_}}\" */\n",$_));
	}

@a=grep(defined($ln{$nid{$_}}),0 .. $n);
foreach (sort { $ln{$nid{$a}} cmp $ln{$nid{$b}} } @a)
	{
	push(@ln,sprintf("%2d,\t/* \"$ln{$nid{$_}}\" */\n",$_));
	}

@a=grep(defined($obj{$nid{$_}}),0 .. $n);
foreach (sort obj_cmp @a)
	{
	$m=$obj{$nid{$_}};
	$v=$objd{$m};
	$v =~ s/L//g;
	$v =~ s/,/ /g;
	push(@ob,sprintf("%2d,\t/* %-32s %s */\n",$_,$m,$v));
	}

print OUT <<'EOF';
/* THIS FILE IS GENERATED FROM objects.h by obj_dat.pl via the
 * following command:
 * perl obj_dat.pl ../../include/openssl/obj_mac.h obj_dat.h */

/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
 * All rights reserved.
 *
 * This package is an SSL implementation written
 * by Eric Young (eay@cryptsoft.com).
 * The implementation was written so as to conform with Netscapes SSL.
 *
 * This library is free for commercial and non-commercial use as long as
 * the following conditions are aheared to.  The following conditions
 * apply to all code found in this distribution, be it the RC4, RSA,
 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
 * included with this distribution is covered by the same copyright terms
 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
 *
 * Copyright remains Eric Young's, and as such any Copyright notices in
 * the code are not to be removed.
 * If this package is used in a product, Eric Young should be given attribution
 * as the author of the parts of the library used.
 * This can be in the form of a textual message at program startup or
 * in documentation (online or textual) provided with the package.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *    "This product includes cryptographic software written by
 *     Eric Young (eay@cryptsoft.com)"
 *    The word 'cryptographic' can be left out if the rouines from the library
 *    being used are not cryptographic related :-).
 * 4. If you include any Windows specific code (or a derivative thereof) from
 *    the apps directory (application code) you must include an acknowledgement:
 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
 *
 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * The licence and distribution terms for any publically available version or
 * derivative of this code cannot be changed.  i.e. this code cannot simply be
 * copied and put under another distribution licence
 * [including the GNU Public Licence.] */

EOF

printf OUT "#define NUM_NID %d\n",$n;
printf OUT "#define NUM_SN %d\n",$#sn+1;
printf OUT "#define NUM_LN %d\n",$#ln+1;
printf OUT "#define NUM_OBJ %d\n\n",$#ob+1;

printf OUT "static const unsigned char lvalues[%d]={\n",$lvalues+1;
print OUT @lvalues;
print OUT "};\n\n";

printf OUT "static const ASN1_OBJECT kObjects[NUM_NID]={\n";
foreach (@out)
	{
	if (length($_) > 75)
		{
		$out="";
		foreach (split(/,/))
			{
			$t=$out.$_.",";
			if (length($t) > 70)
				{
				print OUT "$out\n";
				$t="\t$_,";
				}
			$out=$t;
			}
		chop $out;
		print OUT "$out";
		}
	else
		{ print OUT $_; }
	}
print  OUT "};\n\n";

printf OUT "static const unsigned int kNIDsInShortNameOrder[NUM_SN]={\n";
print  OUT @sn;
print  OUT "};\n\n";

printf OUT "static const unsigned int kNIDsInLongNameOrder[NUM_LN]={\n";
print  OUT @ln;
print  OUT "};\n\n";

printf OUT "static const unsigned int kNIDsInOIDOrder[NUM_OBJ]={\n";
print  OUT @ob;
print  OUT "};\n\n";

close OUT;

sub der_it
	{
	local($v)=@_;
	local(@a,$i,$ret,@r);

	@a=split(/\s+/,$v);
	$ret.=pack("C*",$a[0]*40+$a[1]);
	shift @a;
	shift @a;
	foreach (@a)
		{
		@r=();
		$t=0;
		while ($_ >= 128)
			{
			$x=$_%128;
			$_/=128;
			push(@r,((($t++)?0x80:0)|$x));
			}
		push(@r,((($t++)?0x80:0)|$_));
		$ret.=pack("C*",reverse(@r));
		}
	return($ret);
	}
