windows-nt/Source/XPSP1/NT/multimedia/directx/dinput/dx7/dll/mkhdr.pl
2020-09-26 16:20:57 +08:00

188 lines
4.5 KiB
Perl

#!perl
#
# hsplit is too lame to handle OLE interfaces, so I have to
# write this program myself. It only handles the OLE stuff;
# I leave hsplit to manage the regular % stuff.
#
# Makes it clearer what's going on when we pass it as a flag
$A = 0;
$W = 1;
#
# Dummy prototype gizmos for EmitWrapper.
#
@proto = (
"p",
"p,a",
"p,a,b",
"p,a,b,c",
"p,a,b,c,d",
"p,a,b,c,d,e",
"p,a,b,c,d,e,f",
"p,a,b,c,d,e,f,g",
"p,a,b,c,d,e,f,g,h",
);
##############################################################################
#
# Main loop
#
# Things between ";begin_doc" and ";end_doc" are ignored.
#
# Else, echo everything that isn't between ";begin_interface" and
# ";end_interface". For the stuff between, collect it. If the
# interface name contains a "%", then emit separate W and A versions.
#
##############################################################################
while (<>) {
if (/^;begin_doc$/) {
while (<>) {
last if $_ eq ";end_doc\n";
}
next;
}
($itf) = /^;begin_interface\s+(\S+)/;
unless ($itf) {
print;
next;
}
# Oh boy, we found the start of an interface.
# Collect the methods.
$_ = <>;
die ";begin_methods expected here" unless $_ eq ";begin_methods\n";
# An interface is an array of methods
# A method is an array, $m[0] is the method name, $m[1] is the arglist
@itf = ();
while (<>) {
last if $_ eq ";end_methods\n";
($m, $arg) = /^;method\s+(\S+)\s*\((.*)\)$/;
push(@itf, [ $m, $arg ]) if $m;
}
$_ = <>;
die ";end_interface expected here" unless $_ eq ";end_interface\n";
if ($itf =~ /%/) {
&DoItf($W, $itf, @itf);
&DoItf($A, $itf, @itf);
} else {
&DoItf($W, $itf, @itf);
}
&DoAfterItf($itf, @itf);
}
##############################################################################
#
# Given a line, remove percent signs, converting to W or A accordingly.
#
##############################################################################
sub DePercent {
my($fW, $line) = @_;
if ($fW) {
$line =~ s/STR%/WSTR/g;
$line =~ s/%/W/g;
} else {
$line =~ s/STR%/STR/g;
$line =~ s/%/A/g;
}
$line;
}
##############################################################################
#
# Emit the interface definition.
#
##############################################################################
sub DoItf {
my($fW, $itf, @itf) = @_;
$itf = &DePercent($fW, $itf);
print <<EOI;
#undef INTERFACE
#define INTERFACE $itf
DECLARE_INTERFACE_($itf, IUnknown)
{
/*** IUnknown methods ***/
STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
STDMETHOD_(ULONG,AddRef)(THIS) PURE;
STDMETHOD_(ULONG,Release)(THIS) PURE;
/*** $itf methods ***/
EOI
for (@itf) {
my($m, $arg) = @$_;
print " STDMETHOD($m)(THIS";
print "_ " if $arg;
print &DePercent($fW, $arg);
print ") PURE;\n";
}
print "};\n\n";
my($uc) = uc $itf;
$uc =~s/^I//;
print &DePercent($W, "typedef struct $itf *LP$uc;\n");
print "\n";
}
##############################################################################
#
# Emit the follow-up stuff that comes after an interface definition.
# If the interface name contains a percent sign, emit the appropriate
# mix.
#
##############################################################################
sub DoAfterItf {
my($itf, @itf) = @_;
my($uc) = uc $itf;
$uc =~s/^I//;
my($itfP) = $itf;
$itfP =~ s/%//;
my($ucP) = $uc;
$ucP =~ s/%//;
if ($itf =~ /%/) {
print "#ifdef UNICODE\n";
print &DePercent($W, "#define IID_$itfP IID_$itf\n");
print &DePercent($W, "typedef struct $itf $itfP;\n");
print &DePercent($W, "#define ${itfP}Vtbl ${itf}Vtbl\n");
print "#else\n";
print &DePercent($A, "#define IID_$itfP IID_$itf\n");
print &DePercent($A, "typedef struct $itf $itfP;\n");
print &DePercent($A, "#define ${itfP}Vtbl ${itf}Vtbl\n");
print "#endif\n";
print &DePercent($W, "typedef struct $itfP *LP$ucP;\n");
}
# Now the lame-o wrappers.
print "\n#if !defined(__cplusplus) || defined(CINTERFACE)\n";
&EmitWrapper($itfP, "QueryInterface", 2);
&EmitWrapper($itfP, "AddRef", 0);
&EmitWrapper($itfP, "Release", 0);
for (@itf) {
my($m, $arg, $arity) = @$_;
if ($arg) {
$arity = 1 + y/,/,/;
} else {
$arity = 0;
}
&EmitWrapper($itfP, $m, $arity);
}
print "#endif\n";
}
sub EmitWrapper {
my($itf, $m, $arity) = @_;
die "Need to add another arity" if $arity > $#proto;
print "#define ${itf}_$m($proto[$arity]) (p)->lpVtbl->$m($proto[$arity])\n";
}