188 lines
4.5 KiB
Perl
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";
|
|
}
|
|
|