Blame src/util/def-check.pl

Packit fd8b60
#!/usr/athena/bin/perl -w
Packit fd8b60
Packit fd8b60
# Code initially generated by s2p
Packit fd8b60
# Code modified to use strict and IO::File
Packit fd8b60
Packit fd8b60
eval 'exec /usr/athena/bin/perl -S $0 ${1+"$@"}'
Packit fd8b60
    if 0; # line above evaluated when running under some shell (i.e., not perl)
Packit fd8b60
Packit fd8b60
use strict;
Packit fd8b60
use IO::File;
Packit fd8b60
Packit fd8b60
my $verbose = 0;
Packit fd8b60
my $error = 0;
Packit fd8b60
if ( $ARGV[0] eq "-v" ) { $verbose = 1; shift @ARGV; }
Packit fd8b60
my $h_filename = shift @ARGV || die "usage: $0 [-v] header-file [def-file]\n";
Packit fd8b60
my $d_filename = shift @ARGV;
Packit fd8b60
Packit fd8b60
my $h = open_always($h_filename);
Packit fd8b60
my $d = open_always($d_filename) if $d_filename;
Packit fd8b60
Packit fd8b60
sub open_always
Packit fd8b60
{
Packit fd8b60
    my $file = shift || die;
Packit fd8b60
    my $handle = new IO::File "<$file";
Packit fd8b60
    die "Could not open $file\n" if !$handle;
Packit fd8b60
    return $handle;
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
my @convW = ();
Packit fd8b60
my @convC = ();
Packit fd8b60
my @convK = ();
Packit fd8b60
my @convD = ();
Packit fd8b60
my @vararg = ();
Packit fd8b60
Packit fd8b60
my $len1;
Packit fd8b60
my %conv;
Packit fd8b60
my $printit;
Packit fd8b60
my $vararg;
Packit fd8b60
Packit fd8b60
LINE:
Packit fd8b60
while (! $h->eof()) {
Packit fd8b60
    $_ = $h->getline();
Packit fd8b60
    chop;
Packit fd8b60
    # get calling convention info for function decls
Packit fd8b60
    # what about function pointer typedefs?
Packit fd8b60
    # need to verify unhandled syntax actually triggers a report, not ignored
Packit fd8b60
    # blank lines
Packit fd8b60
    if (/^[ \t]*$/) {
Packit fd8b60
        next LINE;
Packit fd8b60
    }
Packit fd8b60
  Top:
Packit fd8b60
    # drop KRB5INT_BEGIN_DECLS and KRB5INT_END_DECLS
Packit fd8b60
    if (/^ *(KRB5INT|GSSAPI[A-Z]*)_(BEGIN|END)_DECLS/) {
Packit fd8b60
        next LINE;
Packit fd8b60
    }
Packit fd8b60
    # drop preprocessor directives
Packit fd8b60
    if (/^ *#/) {
Packit fd8b60
	while (/\\$/) { $_ .= $h->getline(); }
Packit fd8b60
        next LINE;
Packit fd8b60
    }
Packit fd8b60
    if (/^ *\?==/) {
Packit fd8b60
        next LINE;
Packit fd8b60
    }
Packit fd8b60
    s/#.*$//;
Packit fd8b60
    if (/^\} *$/) {
Packit fd8b60
        next LINE;
Packit fd8b60
    }
Packit fd8b60
    # strip comments
Packit fd8b60
  Cloop1:
Packit fd8b60
    if (/\/\*./) {
Packit fd8b60
	s;/\*[^*]*;/*;;
Packit fd8b60
	s;/\*\*([^/]);/*$1;;
Packit fd8b60
	s;/\*\*$;/*;;
Packit fd8b60
	s;/\*\*/; ;g;
Packit fd8b60
	goto Cloop1;
Packit fd8b60
    }
Packit fd8b60
    # multi-line comments?
Packit fd8b60
    if (/\/\*$/) {
Packit fd8b60
	$_ .= " ";
Packit fd8b60
	$len1 = length;
Packit fd8b60
	$_ .= $h->getline();
Packit fd8b60
	chop if $len1 < length;
Packit fd8b60
	goto Cloop1 if /\/\*./;
Packit fd8b60
    }
Packit fd8b60
    # blank lines
Packit fd8b60
    if (/^[ \t]*$/) {
Packit fd8b60
        next LINE;
Packit fd8b60
    }
Packit fd8b60
    if (/^ *extern "C" \{/) {
Packit fd8b60
        next LINE;
Packit fd8b60
    }
Packit fd8b60
    s/KRB5_ATTR_DEPRECATED//;
Packit fd8b60
    # elide struct definitions
Packit fd8b60
  Struct1:
Packit fd8b60
    if (/\{[^}]*\}/) {
Packit fd8b60
	s/\{[^}]*\}/ /g;
Packit fd8b60
	goto Struct1;
Packit fd8b60
    }
Packit fd8b60
    # multi-line defs
Packit fd8b60
    if (/\{/) {
Packit fd8b60
	$_ .= "\n";
Packit fd8b60
	$len1 = length;
Packit fd8b60
	$_ .= $h->getline();
Packit fd8b60
	chop if $len1 < length;
Packit fd8b60
	goto Struct1;
Packit fd8b60
    }
Packit fd8b60
  Semi:
Packit fd8b60
    unless (/;/) {
Packit fd8b60
	$_ .= "\n";
Packit fd8b60
	$len1 = length;
Packit fd8b60
	$_ .= $h->getline();
Packit fd8b60
	chop if $len1 < length;
Packit fd8b60
	s/\n/ /g;
Packit fd8b60
	s/[ \t]+/ /g;
Packit fd8b60
	s/^[ \t]*//;
Packit fd8b60
	goto Top;
Packit fd8b60
    }
Packit fd8b60
    if (/^typedef[^;]*;/) {
Packit fd8b60
	s/^typedef[^;]*;//g;
Packit fd8b60
	goto Semi;
Packit fd8b60
    }
Packit fd8b60
    if (/^struct[^\(\)]*;/) {
Packit fd8b60
	s/^struct[^\(\)]*;//g;
Packit fd8b60
	goto Semi;
Packit fd8b60
    }
Packit fd8b60
    # should just have simple decls now; split lines at semicolons
Packit fd8b60
    s/ *;[ \t]*$//;
Packit fd8b60
    s/ *;/\n/g;
Packit fd8b60
    if (/^[ \t]*$/) {
Packit fd8b60
        next LINE;
Packit fd8b60
    }
Packit fd8b60
    s/[ \t]*$//;
Packit fd8b60
    goto Notfunct unless /\(.*\)/;
Packit fd8b60
    # Get rid of KRB5_PROTOTYPE
Packit fd8b60
    s/KRB5_PROTOTYPE//;
Packit fd8b60
    s/KRB5_STDARG_P//;
Packit fd8b60
    # here, is probably function decl
Packit fd8b60
    # strip simple arg list - parens, no parens inside; discard, iterate.
Packit fd8b60
    # the iteration should deal with function pointer args.
Packit fd8b60
    $vararg = /\.\.\./;
Packit fd8b60
  Striparg:
Packit fd8b60
    if (/ *\([^\(\)]*\)/) {
Packit fd8b60
	s/ *\([^\(\)]*\)//g;
Packit fd8b60
	goto Striparg;
Packit fd8b60
    }
Packit fd8b60
    # Also strip out attributes, or what's left over of them.
Packit fd8b60
    if (/__attribute__/) {
Packit fd8b60
	s/[ \t]*__attribute__[ \t]*//g;
Packit fd8b60
	goto Striparg;
Packit fd8b60
    }
Packit fd8b60
    # replace return type etc with one token indicating calling convention
Packit fd8b60
    if (/CALLCONV/) {
Packit fd8b60
	if (/\bKRB5_CALLCONV_WRONG\b/) {
Packit fd8b60
	    s/^.*KRB5_CALLCONV_WRONG *//;
Packit fd8b60
	    die "Invalid function name: '$_'" if (!/^[A-Za-z0-9_]+$/);
Packit fd8b60
	    push @convW, $_;
Packit fd8b60
	    push @vararg, $_ if $vararg;
Packit fd8b60
	} elsif (/\bKRB5_CALLCONV_C\b/) {
Packit fd8b60
	    s/^.*KRB5_CALLCONV_C *//;
Packit fd8b60
	    die "Invalid function name: '$_'" if (!/^[A-Za-z0-9_]+$/);
Packit fd8b60
	    push @convC, $_;
Packit fd8b60
	    push @vararg, $_ if $vararg;
Packit fd8b60
	} elsif (/\bKRB5_CALLCONV\b/) {
Packit fd8b60
	    s/^.*KRB5_CALLCONV *//;
Packit fd8b60
	    die "Invalid function name: '$_'" if (!/^[A-Za-z0-9_]+$/);
Packit fd8b60
	    push @convK, $_;
Packit fd8b60
	    push @vararg, $_ if $vararg;
Packit fd8b60
	} else {
Packit fd8b60
	    die "Unrecognized calling convention while parsing: '$_'\n";
Packit fd8b60
	}
Packit fd8b60
	goto Hadcallc;
Packit fd8b60
    }
Packit fd8b60
    # deal with no CALLCONV indicator
Packit fd8b60
    s/^.* \**(\w+) *$/$1/;
Packit fd8b60
    die "Invalid function name: '$_'" if (!/^[A-Za-z0-9_]+$/);
Packit fd8b60
    push @convD, $_;
Packit fd8b60
    push @vararg, $_ if $vararg;
Packit fd8b60
  Hadcallc:
Packit fd8b60
    goto Skipnotf;
Packit fd8b60
  Notfunct:
Packit fd8b60
    # probably a variable
Packit fd8b60
    s/^/VARIABLE_DECL /;
Packit fd8b60
  Skipnotf:
Packit fd8b60
    # toss blank lines
Packit fd8b60
    if (/^[ \t]*$/) {
Packit fd8b60
        next LINE;
Packit fd8b60
    }
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
if ( $verbose ) {
Packit fd8b60
    print join("\n\t", "Using default calling convention:", sort(@convD));
Packit fd8b60
    print join("\n\t", "\nUsing KRB5_CALLCONV:", sort(@convK));
Packit fd8b60
    print join("\n\t", "\nUsing KRB5_CALLCONV_C:", sort(@convC));
Packit fd8b60
    print join("\n\t", "\nUsing KRB5_CALLCONV_WRONG:", sort(@convW));
Packit fd8b60
    print "\n","-"x70,"\n";
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
%conv = ();
Packit fd8b60
map { $conv{$_} = "default"; } @convD;
Packit fd8b60
map { $conv{$_} = "KRB5_CALLCONV"; } @convK;
Packit fd8b60
map { $conv{$_} = "KRB5_CALLCONV_C"; } @convC;
Packit fd8b60
map { $conv{$_} = "KRB5_CALLCONV_WRONG"; } @convW;
Packit fd8b60
Packit fd8b60
my %vararg = ();
Packit fd8b60
map { $vararg{$_} = 1; } @vararg;
Packit fd8b60
Packit fd8b60
if (!$d) {
Packit fd8b60
    print "No .DEF file specified\n" if $verbose;
Packit fd8b60
    exit 0;
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
LINE2:
Packit fd8b60
while (! $d->eof()) {
Packit fd8b60
    $_ = $d->getline();
Packit fd8b60
    chop;
Packit fd8b60
    #
Packit fd8b60
    if (/^;/) {
Packit fd8b60
        $printit = 0;
Packit fd8b60
        next LINE2;
Packit fd8b60
    }
Packit fd8b60
    if (/^[ \t]*$/) {
Packit fd8b60
        $printit = 0;
Packit fd8b60
        next LINE2;
Packit fd8b60
    }
Packit fd8b60
    if (/^EXPORTS/ || /^DESCRIPTION/ || /^HEAPSIZE/) {
Packit fd8b60
        $printit = 0;
Packit fd8b60
        next LINE2;
Packit fd8b60
    }
Packit fd8b60
    s/[ \t]*//g;
Packit fd8b60
    s/@[0-9]+//;
Packit fd8b60
    my($xconv);
Packit fd8b60
    if (/PRIVATE/ || /INTERNAL/) {
Packit fd8b60
	$xconv = "PRIVATE";
Packit fd8b60
    } elsif (/DATA/) {
Packit fd8b60
	$xconv = "DATA";
Packit fd8b60
    } elsif (/!CALLCONV/ || /KRB5_CALLCONV_WRONG/) {
Packit fd8b60
	$xconv = "KRB5_CALLCONV_WRONG";
Packit fd8b60
    } elsif ($vararg{$_}) {
Packit fd8b60
	$xconv = "KRB5_CALLCONV_C";
Packit fd8b60
    } else {
Packit fd8b60
	$xconv = "KRB5_CALLCONV";
Packit fd8b60
    }
Packit fd8b60
    s/;.*$//;
Packit fd8b60
Packit fd8b60
    if ($xconv eq "PRIVATE") {
Packit fd8b60
	print "\t private $_\n" if $verbose;
Packit fd8b60
	next LINE2;
Packit fd8b60
    }
Packit fd8b60
    if ($xconv eq "DATA") {
Packit fd8b60
	print "\t data $_\n" if $verbose;
Packit fd8b60
	next LINE2;
Packit fd8b60
    }
Packit fd8b60
    if (!defined($conv{$_})) {
Packit fd8b60
	print "No calling convention specified for $_!\n";
Packit fd8b60
	$error = 1;
Packit fd8b60
    } elsif (! ($conv{$_} eq $xconv)) {
Packit fd8b60
	print "Function $_ should have calling convention '$xconv', but has '$conv{$_}' instead.\n";
Packit fd8b60
	$error = 1;
Packit fd8b60
    } else {
Packit fd8b60
#	print "Function $_ is okay.\n";
Packit fd8b60
    }
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
#print "Calling conventions defined for: ", keys(%conv);
Packit fd8b60
exit $error;