line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
|
2
|
|
|
|
|
|
|
package Inline::WSC;
|
3
|
|
|
|
|
|
|
|
4
|
1
|
|
|
1
|
|
63116
|
use strict;
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
34
|
|
5
|
1
|
|
|
1
|
|
6
|
use warnings;
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
23
|
|
6
|
1
|
|
|
1
|
|
400
|
use Win32::OLE;
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
use Digest::MD5 'md5_hex';
|
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
our $VERSION = 0.02;
|
10
|
|
|
|
|
|
|
my $WSC_DIR = $ENV{TMP} || $ENV{TEMP} || 'C:\Windows\Temp';
|
11
|
|
|
|
|
|
|
die "Temporary directory '$WSC_DIR' does not exist" unless -d $WSC_DIR;
|
12
|
|
|
|
|
|
|
die "Temporary directory '$WSC_DIR' is not writable" unless -w $WSC_DIR;
|
13
|
|
|
|
|
|
|
our $WSC_PREFIX = 'InlineWin32COM.WSC';
|
14
|
|
|
|
|
|
|
my @ToDelete = ();
|
15
|
|
|
|
|
|
|
my %MethodMapping = ();
|
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
#==============================================================================
|
18
|
|
|
|
|
|
|
# Called when this module is 'use'd:
|
19
|
|
|
|
|
|
|
sub import
|
20
|
|
|
|
|
|
|
{
|
21
|
|
|
|
|
|
|
my ($s, $language, $code) = @_;
|
22
|
|
|
|
|
|
|
return unless
|
23
|
|
|
|
|
|
|
( defined($language) && defined($code) ) &&
|
24
|
|
|
|
|
|
|
( length($language) && length($code) );
|
25
|
|
|
|
|
|
|
my $caller = caller;
|
26
|
|
|
|
|
|
|
my @methods = $s->_init( $language, $code );
|
27
|
|
|
|
|
|
|
$s->_export_methods( $caller, \@methods );
|
28
|
|
|
|
|
|
|
}# end import()
|
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
#==============================================================================
|
32
|
|
|
|
|
|
|
# Alias to import:
|
33
|
|
|
|
|
|
|
*compile = \&import;
|
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
#==============================================================================
|
37
|
|
|
|
|
|
|
# Writes the *.wsc file to disk:
|
38
|
|
|
|
|
|
|
sub _init
|
39
|
|
|
|
|
|
|
{
|
40
|
|
|
|
|
|
|
my ($s, $language, $code) = @_;
|
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
my $md5 = md5_hex($code);
|
43
|
|
|
|
|
|
|
my $classname = "$WSC_PREFIX\_$md5.wsc";
|
44
|
|
|
|
|
|
|
my @methods = $s->_get_method_names( $code );
|
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
# Die when we encounter function redefinitions:
|
47
|
|
|
|
|
|
|
foreach( @methods )
|
48
|
|
|
|
|
|
|
{
|
49
|
|
|
|
|
|
|
die "Method '$_' was already defined in file '$MethodMapping{$_}'"
|
50
|
|
|
|
|
|
|
if $MethodMapping{$_};
|
51
|
|
|
|
|
|
|
$MethodMapping{$_} = $classname;
|
52
|
|
|
|
|
|
|
}# end foreach()
|
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
my $wsc_code = $s->_make_wsc_code( $language, $code, $classname, \@methods );
|
55
|
|
|
|
|
|
|
my $filename = "$WSC_DIR\\$classname";
|
56
|
|
|
|
|
|
|
push @ToDelete, $filename;
|
57
|
|
|
|
|
|
|
open my $ofh, '>', $filename;
|
58
|
|
|
|
|
|
|
print $ofh $wsc_code;
|
59
|
|
|
|
|
|
|
close($ofh);
|
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
return @methods;
|
62
|
|
|
|
|
|
|
}# end _init()
|
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
#==============================================================================
|
66
|
|
|
|
|
|
|
# Assembles the *.wsc code:
|
67
|
|
|
|
|
|
|
sub _make_wsc_code
|
68
|
|
|
|
|
|
|
{
|
69
|
|
|
|
|
|
|
my ($s, $language, $code, $classname, $methods) = @_;
|
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
my $methodcode = join("\n",
|
72
|
|
|
|
|
|
|
map qq{}, @$methods
|
73
|
|
|
|
|
|
|
);
|
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
return <<"EOF";
|
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
description = "Inline::WSC Class"
|
80
|
|
|
|
|
|
|
progid = "$classname"
|
81
|
|
|
|
|
|
|
version = "1.0"
|
82
|
|
|
|
|
|
|
>
|
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
$methodcode
|
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
EOF
|
95
|
|
|
|
|
|
|
}# end _make_wsc_code()
|
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
#==============================================================================
|
99
|
|
|
|
|
|
|
# Scans the code for declarations of functions and subs.
|
100
|
|
|
|
|
|
|
sub _get_method_names
|
101
|
|
|
|
|
|
|
{
|
102
|
|
|
|
|
|
|
my ($s, $code) = @_;
|
103
|
|
|
|
|
|
|
my @out = ();
|
104
|
|
|
|
|
|
|
FUNC: while($code =~ m/\s*(function|sub)\s+([a-z0-9_]+)\s*(?:\(.*?\))?/isgx)
|
105
|
|
|
|
|
|
|
{
|
106
|
|
|
|
|
|
|
local $^W = 0;
|
107
|
|
|
|
|
|
|
push @out, $2;
|
108
|
|
|
|
|
|
|
}# end while()
|
109
|
|
|
|
|
|
|
return @out;
|
110
|
|
|
|
|
|
|
}# end _get_method_names()
|
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
#==============================================================================
|
114
|
|
|
|
|
|
|
# Pollute the caller's namespace with the methods defined in the various code
|
115
|
|
|
|
|
|
|
# fragments we were passed.
|
116
|
|
|
|
|
|
|
sub _export_methods
|
117
|
|
|
|
|
|
|
{
|
118
|
|
|
|
|
|
|
my ($s, $caller, $methods) = @_;
|
119
|
|
|
|
|
|
|
no strict 'refs';
|
120
|
|
|
|
|
|
|
foreach my $method ( @$methods )
|
121
|
|
|
|
|
|
|
{
|
122
|
|
|
|
|
|
|
my $WscClass = $MethodMapping{$method};
|
123
|
|
|
|
|
|
|
my $ob = Win32::OLE->GetObject("script:$WSC_DIR\\$WscClass")
|
124
|
|
|
|
|
|
|
or die "Couldn't create OLE '$WscClass':\n" . Win32::GetLastError . " ";
|
125
|
|
|
|
|
|
|
# The sub exists as a closure - saves us the call to GetObject() every time
|
126
|
|
|
|
|
|
|
# the method is called:
|
127
|
|
|
|
|
|
|
*{"$caller\::$method"} = sub {
|
128
|
|
|
|
|
|
|
return $ob->$method(@_);
|
129
|
|
|
|
|
|
|
};
|
130
|
|
|
|
|
|
|
}# end foreach()
|
131
|
|
|
|
|
|
|
}# end _export_methods()
|
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
1;# return true:
|
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
__END__
|