X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=game%2Fdefault%2Fdpdefs%2Fsource_compare.pl;fp=game%2Fdefault%2Fdpdefs%2Fsource_compare.pl;h=01dbfd4953c44841687a771994b84e6bce6e22bd;hb=697777799c5b607a6120481eb191cbdf142ced93;hp=0000000000000000000000000000000000000000;hpb=90ab66ba6bfed05c0ce331d321ff63eba7912637;p=xonotic%2Fdarkplaces.git diff --git a/game/default/dpdefs/source_compare.pl b/game/default/dpdefs/source_compare.pl new file mode 100755 index 00000000..01dbfd49 --- /dev/null +++ b/game/default/dpdefs/source_compare.pl @@ -0,0 +1,269 @@ +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;