wrath-darkplaces/dpdefs/source_compare.pl

270 lines
5.3 KiB
Perl

use strict;
use warnings;
my %vm = (
menu => {},
csprogs => {},
progs => {}
);
my $skip = 0;
my $parsing_builtins = undef;
my $parsing_builtin = 0;
my $parsing_fields = undef;
my $parsing_globals = undef;
my $parsing_vm = undef;
for(<../*.h>, <../*.c>)
{
open my $fh, "<", $_
or die "<$_: $!";
while(<$fh>)
{
chomp;
if(/^#if 0$/)
{
$skip = 1;
}
elsif(/^#else$/)
{
$skip = 0;
}
elsif(/^#endif$/)
{
$skip = 0;
}
elsif($skip)
{
}
elsif(/^prvm_builtin_t vm_m_/)
{
$parsing_builtins = "menu";
$parsing_builtin = 0;
}
elsif(/^prvm_builtin_t vm_cl_/)
{
$parsing_builtins = "csprogs";
$parsing_builtin = 0;
}
elsif(/^prvm_builtin_t vm_sv_/)
{
$parsing_builtins = "progs";
$parsing_builtin = 0;
}
elsif(/^\}/)
{
$parsing_builtins = undef;
$parsing_globals = undef;
$parsing_fields = undef;
$parsing_vm = undef;
}
elsif(/^typedef struct entvars_s$/)
{
$parsing_fields = "fields";
$parsing_vm = "progs";
}
elsif(/^typedef struct cl_entvars_s$/)
{
$parsing_fields = "fields";
$parsing_vm = "csprogs";
}
elsif(/^typedef struct prvm_prog_fieldoffsets_s$/)
{
$parsing_fields = "fields";
}
elsif(/^typedef struct globalvars_s$/)
{
$parsing_globals = "globals";
$parsing_vm = "progs";
}
elsif(/^typedef struct cl_globalvars_s$/)
{
$parsing_globals = "globals";
$parsing_vm = "csprogs";
}
elsif(/^typedef struct m_globalvars_s$/)
{
$parsing_globals = "globals";
$parsing_vm = "menu";
}
elsif(/^typedef struct prvm_prog_globaloffsets_s$/)
{
$parsing_globals = "globals";
}
elsif($parsing_builtins)
{
s/\/\*.*?\*\// /g;
if(/^\s*\/\//)
{
}
elsif(/^NULL\b/)
{
$parsing_builtin += 1;
}
elsif(/^(\w+)\s*,?\s*\/\/\s+#(\d+)\s*(.*)/)
{
my $func = $1;
my $builtin = int $2;
my $descr = $3;
my $extension = "DP_UNKNOWN";
if($descr =~ s/\s+\(([0-9A-Z_]*)\)//)
{
$extension = $1;
}
# 'void(vector ang) makevectors'
if($descr eq "")
{
}
elsif($descr eq "draw functions...")
{
}
elsif($descr =~ /^\/\//)
{
}
elsif($descr =~ /\) (\w+)/)
{
$func = $1;
}
elsif($descr =~ /(\w+)\s*\(/)
{
$func = $1;
}
elsif($descr =~ /^\w+$/)
{
$func = $descr;
}
else
{
warn "No function name found in $descr";
}
warn "builtin sequence error: #$builtin (expected: $parsing_builtin)"
if $builtin != $parsing_builtin;
$parsing_builtin = $builtin + 1;
$vm{$parsing_builtins}{builtins}[$builtin] = [0, $func, $extension];
}
else
{
warn "Fails to parse: $_";
}
}
elsif($parsing_fields || $parsing_globals)
{
my $f = $parsing_fields || $parsing_globals;
if(/^\s*\/\//)
{
}
elsif(/^\s+(?:int|float|string_t|vec3_t|func_t)\s+(\w+);\s*(?:\/\/(.*))?/)
{
my $name = $1;
my $descr = $2 || "";
my $extension = "DP_UNKNOWN";
$extension = $1
if $descr =~ /\b([0-9A-Z_]+)\b/;
my $found = undef;
$vm{menu}{$f}{$name} = ($found = [0, $extension])
if $descr =~ /common|menu/;
$vm{progs}{$f}{$name} = ($found = [0, $extension])
if $descr =~ /common|ssqc/;
$vm{csprogs}{$f}{$name} = ($found = [0, $extension])
if $descr =~ /common|csqc/;
$vm{$parsing_vm}{$f}{$name} = ($found = [0, $extension])
if not defined $found and defined $parsing_vm;
warn "$descr does not yield info about target VM"
if not defined $found;
}
}
elsif(/getglobal\w*\(\w+, "(\w+)"\)/)
{
# hack for weird DP source
$vm{csprogs}{globals}{$1} = [0, "DP_CSQC_SPAWNPARTICLE"];
}
}
close $fh;
}
# now read in dpdefs
for((
["csprogsdefs.qc", "csprogs"],
["dpextensions.qc", "progs"],
["menudefs.qc", "menu"],
["progsdefs.qc", "progs"]
))
{
my ($file, $v) = @$_;
open my $fh, "<", "$file"
or die "<$file: $!";
while(<$fh>)
{
s/\/\/.*//;
if(/^(?:float|entity|string|vector)\s+((?:\w+\s*,\s*)*\w+)\s*;/)
{
for(split /\s*,\s*/, $1)
{
print "// $v: Global $_ declared but not defined\n"
if not $vm{$v}{globals}{$_};
$vm{$v}{globals}{$_}[0] = 1; # documented!
}
}
elsif(/^\.(?:float|entity|string|vector|void)(?:.*\))?\s+((?:\w+\s*,\s*)*\w+)\s*;/)
{
for(split /\s*,\s*/, $1)
{
print "// $v: Field $_ declared but not defined\n"
if not $vm{$v}{fields}{$_};
$vm{$v}{fields}{$_}[0] = 1; # documented!
}
}
elsif(/#(\d+)/)
{
print "// $v: Builtin #$1 declared but not defined\n"
if not $vm{$v}{builtins}[$1];
$vm{$v}{builtins}[$1][0] = 1; # documented!
}
else
{
}
}
close $fh;
}
# some dumb output
for my $v(sort keys %vm)
{
print "/******************************************\n";
print " * $v\n";
print " ******************************************/\n";
my $b = $vm{$v}{builtins};
for(0..@$b)
{
next if not defined $b->[$_];
my ($documented, $func, $extension) = @{$b->[$_]};
print "float $func(...) = #$_; // $extension\n"
unless $documented;
}
my $g = $vm{$v}{globals};
for(sort keys %$g)
{
my ($documented, $extension) = @{$g->{$_}};
print "float $_; // $extension\n"
unless $documented;
}
my $f = $vm{$v}{fields};
for(sort keys %$f)
{
my ($documented, $extension) = @{$f->{$_}};
print ".float $_; // $extension\n"
unless $documented;
}
}
__END__
use Data::Dumper;
$Data::Dumper::Sortkeys = 1;
print Dumper \%vm;