270 lines
5.3 KiB
Perl
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;
|