
#! /usr/bin/env perl
# Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the Apache License 2.0 (the "License").  You may not use
# this file except in compliance with the License.  You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html

use strict;
use warnings;

use Getopt::Long;
use FindBin;
use lib "$FindBin::Bin/perl";

use OpenSSL::Ordinals;
use OpenSSL::ParseC;

my $ordinals_file = undef;      # the ordinals file to use
my $symhacks_file = undef;      # a symbol hacking file (optional)
my $version = undef;            # the version to use for added symbols
my $checkexist = 0;             # (unsure yet)
my $warnings = 1;
my $verbose = 0;
my $debug = 0;

GetOptions('ordinals=s' => \$ordinals_file,
           'symhacks=s' => \$symhacks_file,
           'version=s'  => \$version,
           'exist'      => \$checkexist,
           'warnings!'  => \$warnings,
           'verbose'    => \$verbose,
           'debug'      => \$debug)
    or die "Error in command line arguments\n";

die "Please supply ordinals file\n"
    unless $ordinals_file;

my $ordinals = OpenSSL::Ordinals->new(from => $ordinals_file,
                                      warnings => $warnings,
                                      verbose => $verbose,
                                      debug => $debug);
$ordinals->set_version($version);

my %orig_names = ();
%orig_names = map { $_->name() => 1 }
    $ordinals->items(comparator => sub { $_[0] cmp $_[1] },
                     filter => sub { $_->exists() })
    if $checkexist;

# Invalidate all entries, they get revalidated when we re-check below
$ordinals->invalidate();

foreach my $f (($symhacks_file // (), @ARGV)) {
    print STDERR $f," ","-" x (69 - length($f)),"\n" if $verbose;
    open IN, $f || die "Couldn't open $f: $!\n";
    foreach (parse(<IN>, { filename => $f,
                           warnings => $warnings,
                           verbose => $verbose,
                           debug => $debug })) {
        $_->{value} = $_->{value}||"";
        next if grep { $_ eq 'CONST_STRICT' } @{$_->{conds}};
        printf STDERR "%s> %s%s : %s\n",
            $_->{type},
            $_->{name},
            ($_->{type} eq 'M' && defined $symhacks_file && $f eq $symhacks_file
             ? ' = ' . $_->{value}
             : ''),
            join(', ', @{$_->{conds}})
            if $verbose;
        if ($_->{type} eq 'M'
                && defined $symhacks_file
                && $f eq $symhacks_file
                && $_->{value} =~ /^\w(?:\w|\d)*/) {
            $ordinals->add_alias($_->{value}, $_->{name}, @{$_->{conds}});
        } else {
            next if $_->{returntype} =~ /\b(?:ossl_)inline/;
            my $type = {
                F => 'FUNCTION',
                V => 'VARIABLE',
            } -> {$_->{type}};
            if ($type) {
                $ordinals->add($_->{name}, $type, @{$_->{conds}});
            }
        }
    }
    close IN;
}

# As long as we're running in development or alpha releases, we can have
# symbols without specific numbers assigned.  When in beta or final release,
# all symbols MUST have an assigned number.
if ($version !~ m/^\d+\.\d+\.\d+(?:[a-z]+)?-(?:dev|alpha)/) {
    $ordinals->renumber();
}

if ($checkexist) {
    my %new_names = map { $_->name() => 1 }
        $ordinals->items(comparator => sub { $_[0] cmp $_[1] },
                         filter => sub { $_->exists() });
    # Eliminate common names
    foreach (keys %orig_names) {
        next unless exists $new_names{$_};
        delete $orig_names{$_};
        delete $new_names{$_};
    }
    if (%orig_names) {
        print "The following symbols do not seem to exist in code:\n";
        foreach (sort keys %orig_names) {
            print "\t$_\n";
        }
    }
    if (%new_names) {
        print "The following existing symbols are not in ordinals file:\n";
        foreach (sort keys %new_names) {
            print "\t$_\n";
        }
    }
} else {
    $ordinals->rewrite();
    my %stats = $ordinals->stats();
    print STDERR
        "${ordinals_file}: $stats{modified} old symbols have updated info\n"
        if $stats{modified};
    if ($stats{new}) {
        print STDERR "${ordinals_file}: Added $stats{new} new symbols\n";
    } else {
        print STDERR "${ordinals_file}: No new symbols added\n";
    }
    if ($stats{unassigned}) {
        my $symbol = $stats{unassigned} == 1 ? "symbol" : "symbols";
        my $is = $stats{unassigned} == 1 ? "is" : "are";
        print STDERR "${ordinals_file}: $stats{unassigned} $symbol $is without ordinal number\n";
    }
}
