File Coverage

blib/lib/Inline/WSC.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


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__