|  line  | 
 stmt  | 
 bran  | 
 cond  | 
 sub  | 
 pod  | 
 time  | 
 code  | 
| 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 NAME  | 
| 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Symbol::Approx::Sub - Perl module for calling subroutines by approximate names!  | 
| 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 SYNOPSIS  | 
| 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   use Symbol::Approx::Sub;  | 
| 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   sub a {  | 
| 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # blah...  | 
| 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   aa(); # executes a() if aa() doesn't exist.  | 
| 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
16
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   use Symbol::Approx::Sub (xform => 'Text::Metaphone');  | 
| 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   use Symbol::Approx::Sub (xform => undef,  | 
| 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                            match => 'String::Approx');  | 
| 
19
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   use Symbol::Approx::Sub (xform => 'Text::Soundex');  | 
| 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   use Symbol::Approx::Sub (xform => \&my_transform);  | 
| 
21
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   use Symbol::Approx::Sub (xform => [\&my_transform, 'Text::Soundex']);  | 
| 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   use Symbol::Approx::Sub (xform => \&my_transform,  | 
| 
23
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                            match => \&my_matcher,  | 
| 
24
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                            choose => \&my_chooser);  | 
| 
25
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 New B mode.  | 
| 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
28
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   use Symbol::Approx::Sub (suggest => 1);  | 
| 
29
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 DESCRIPTION  | 
| 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
32
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 This is _really_ stupid. This module allows you to call subroutines by  | 
| 
33
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 _approximate_ names. Why you would ever want to do this is a complete  | 
| 
34
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 mystery to me. It was written as an experiment to see how well I  | 
| 
35
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 understood typeglobs and AUTOLOADing.  | 
| 
36
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
37
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 To use it, simply include the line:  | 
| 
38
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
39
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   use Symbol::Approx::Sub;  | 
| 
40
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
41
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 somewhere in your program. Then, each time you call a subroutine that doesn't  | 
| 
42
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 exist in the current package, Perl will search for a subroutine with  | 
| 
43
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 approximately the same name. The meaning of 'approximately the same' is  | 
| 
44
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 configurable. The default is to find subroutines with the same Soundex  | 
| 
45
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 value (as defined by Text::Soundex) as the missing subroutine. There are  | 
| 
46
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 two other built-in matching styles using Text::Metaphone and  | 
| 
47
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 String::Approx. To use either of these use:  | 
| 
48
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
49
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   use Symbol::Approx::Sub (xform => 'Text::Metaphone');  | 
| 
50
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
51
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 or  | 
| 
52
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
53
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   use Symbol::Approx::Sub (xform => undef,  | 
| 
54
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                            match => 'String::Approx');  | 
| 
55
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
56
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 when using Symbol::Approx::Sub.  | 
| 
57
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
58
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head2 Configuring The Fuzzy Matching  | 
| 
59
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
60
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 There are three phases to the matching process. They are:  | 
| 
61
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
62
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =over 4  | 
| 
63
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
64
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item *  | 
| 
65
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
66
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 B - a transform subroutine applies some kind of transformation  | 
| 
67
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 to the subroutine names. For example the default transformer applies the  | 
| 
68
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Soundex algorithm to each of the subroutine names. Other obvious  | 
| 
69
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 tranformations would be to remove all the underscores or to change the  | 
| 
70
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 names to lower case.  | 
| 
71
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
72
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 A transform subroutine should simply apply its transformation to each  | 
| 
73
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 item in its parameter list and return the transformed list. For example, a  | 
| 
74
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 transformer that removed underscores from its parameters would look like  | 
| 
75
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 this:  | 
| 
76
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
77
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   sub tranformer {  | 
| 
78
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     map { s/_//g; $_ } @_;  | 
| 
79
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
80
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
81
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Transform subroutines can be chained together.  | 
| 
82
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
83
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item *  | 
| 
84
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
85
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 B - a match subroutine takes a target string and a list of other  | 
| 
86
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 strings. It matches each of the strings against the target and determines  | 
| 
87
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 whether or not it 'matches' according to some criteria. For example, the  | 
| 
88
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 default matcher simply checks to see if the strings are equal.  | 
| 
89
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
90
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 A match subroutine is passed the target string as its first parameter,  | 
| 
91
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 followed by the list of potential matches. For each string that matches,  | 
| 
92
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 the matcher should return the index number from the input list. For example,  | 
| 
93
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 the default matcher is implemented like this:  | 
| 
94
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
95
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   sub matcher {  | 
| 
96
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my ($sub, @subs) = @_;  | 
| 
97
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my (@ret);  | 
| 
98
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
99
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     foreach (0 .. $#subs) {  | 
| 
100
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       push @ret, $_ if $sub eq $subs[$_];  | 
| 
101
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
102
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
103
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     @ret;  | 
| 
104
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
105
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
106
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item *  | 
| 
107
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
108
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 B - a chooser subroutine takes a list of matches and chooses exactly  | 
| 
109
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 one item from the list. The default matcher chooses one item at random.  | 
| 
110
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
111
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 A chooser subroutine is passed a list of matches and must simply return one  | 
| 
112
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 index number from that list. For example, the default chooser is implemented  | 
| 
113
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 like this:  | 
| 
114
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
115
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   sub chooser {  | 
| 
116
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     rand @_;  | 
| 
117
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
118
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
119
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =back  | 
| 
120
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
121
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 You can override any of these behaviours by writing your own transformer,  | 
| 
122
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 matcher or chooser. You can either define the subroutine in your own  | 
| 
123
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 script or you can put the subroutine in a separate module which  | 
| 
124
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Symbol::Approx::Sub can then use as a I. See below for more details  | 
| 
125
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 on plug-ins.  | 
| 
126
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
127
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 To use your own function, simply pass a reference to the subroutine to the  | 
| 
128
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 C | 
| 
129
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
130
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   use Symbol::Approx::Sub(xform => \&my_transform,  | 
| 
131
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                           match => \&my_matcher,  | 
| 
132
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                           choose => \&my_chooser);  | 
| 
133
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
134
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 A plug-in is simply a module that lives in the Symbol::Approx::Sub  | 
| 
135
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 namespace. For example, if you had a line of code like this:  | 
| 
136
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
137
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   use Symbol::Approx::Sub(xform => 'MyTransform');  | 
| 
138
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
139
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 then Symbol::Approx::Sub will try to load a module called  | 
| 
140
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Symbol::Approx::Sub::MyTransform and it will use a function from within that  | 
| 
141
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 module called C as the transform function. Similarly, the  | 
| 
142
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 matcher function is called C and the chooser function is called  | 
| 
143
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 C.  | 
| 
144
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
145
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 The default transformer, matcher and chooser are available as plug-ins  | 
| 
146
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 called Text::Soundex, String::Equal and Random.  | 
| 
147
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
148
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head2 Suggest mode  | 
| 
149
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
150
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Version 3.1.0 introduces a 'suggest' mode. In this mode, instead of just  | 
| 
151
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 choosing and running an alternative subroutine, your program will still  | 
| 
152
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 die as it would without Symbol::Approx::Sub, but the error message you  | 
| 
153
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 see will include the suggested alternative subroutine. As an example,  | 
| 
154
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 take this code:  | 
| 
155
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
156
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   sub aa {  | 
| 
157
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     print "Here's aa()";  | 
| 
158
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
159
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
160
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   a();  | 
| 
161
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
162
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Obviously, if you run this without loading Symbol::Approx::Sub, you'll  | 
| 
163
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 get an error message. That message will say "Cannot find subroutine  | 
| 
164
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 main::a". With Symbol::Approx::Sub loaded in its default mode, the  | 
| 
165
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 module will find C instead of C and will silently run that  | 
| 
166
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 subroutine instead.  | 
| 
167
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
168
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 And that's what makes Symbol::Approx::Sub nothing more than a clever  | 
| 
169
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 party trick. It's really not at all useful to run a program when you're  | 
| 
170
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 not really sure what subroutines will be called.  | 
| 
171
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
172
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 But running in 'suggest' mode changes that behaviour. Instead of just  | 
| 
173
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 running C silently, the module will still C (as in the  | 
| 
174
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 non-Symbol::Approx::Sub behaviour) but the message will be a little  | 
| 
175
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 more helpful, as it will include the name of the subroutine that has  | 
| 
176
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 been selected as the most likely correction for your typo.  | 
| 
177
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
178
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 So, if you run this code:  | 
| 
179
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
180
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   use Symbol::Approx::Sub (suggest => 1);  | 
| 
181
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
182
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   sub aa {  | 
| 
183
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     print "Here's aa()";  | 
| 
184
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
185
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
186
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   a();  | 
| 
187
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
188
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Then your program will die with the error message "Cannot find  | 
| 
189
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 subroutine main::a. Did you mean main::aa?".  | 
| 
190
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
191
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 I like to think that some eighteen years or so after it was  | 
| 
192
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 first released, Symbol::Approx::Sub has added a feature that  | 
| 
193
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 might actually be of some use.  | 
| 
194
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
195
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Thanks to Alex Balhatchet for suggesting it.  | 
| 
196
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
197
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =cut  | 
| 
198
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
199
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 package Symbol::Approx::Sub;  | 
| 
200
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
201
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 require 5.010_000;  | 
| 
202
 | 
17
 | 
 
 | 
 
 | 
  
17
  
 | 
 
 | 
991737
 | 
 use strict;  | 
| 
 
 | 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
159
 | 
    | 
| 
 
 | 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
542
 | 
    | 
| 
203
 | 
17
 | 
 
 | 
 
 | 
  
17
  
 | 
 
 | 
89
 | 
 use warnings;  | 
| 
 
 | 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
38
 | 
    | 
| 
 
 | 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
825
 | 
    | 
| 
204
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
205
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our ($VERSION, @ISA, $AUTOLOAD);  | 
| 
206
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
207
 | 
17
 | 
 
 | 
 
 | 
  
17
  
 | 
 
 | 
102
 | 
 use Devel::Symdump;  | 
| 
 
 | 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
34
 | 
    | 
| 
 
 | 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
413
 | 
    | 
| 
208
 | 
17
 | 
 
 | 
 
 | 
  
17
  
 | 
 
 | 
9520
 | 
 use Module::Load;  | 
| 
 
 | 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
19913
 | 
    | 
| 
 
 | 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
109
 | 
    | 
| 
209
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 use Exception::Class (  | 
| 
210
 | 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
190
 | 
   'SAS::Exception',  | 
| 
211
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'SAS::Exception::InvalidOption'              => { isa => 'SAS::Exception' },  | 
| 
212
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'SAS::Exception::InvalidOption::Transformer' => { isa => 'SAS::Exception::InvalidOption' },  | 
| 
213
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'SAS::Exception::InvalidOption::Matcher'     => { isa => 'SAS::Exception::InvalidOption' },  | 
| 
214
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'SAS::Exception::InvalidOption::Chooser'     => { isa => 'SAS::Exception::InvalidOption' },  | 
| 
215
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'SAS::Exception::InvalidParameter'           => { isa => 'SAS::Exception' },  | 
| 
216
 | 
17
 | 
 
 | 
 
 | 
  
17
  
 | 
 
 | 
10267
 | 
 );  | 
| 
 
 | 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
183629
 | 
    | 
| 
217
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
218
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 $VERSION = '3.1.3';  | 
| 
219
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
220
 | 
17
 | 
 
 | 
 
 | 
  
17
  
 | 
 
 | 
25421
 | 
 use Carp;  | 
| 
 
 | 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
34
 | 
    | 
| 
 
 | 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2087
 | 
    | 
| 
221
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
222
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # List of functions that we _never_ try to match approximately.  | 
| 
223
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my @_BARRED = qw(AUTOLOAD BEGIN CHECK INIT DESTROY END);  | 
| 
224
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my %_BARRED = map { $_ => 1 } @_BARRED;  | 
| 
225
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
226
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # import is called when another script uses this module.  | 
| 
227
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # All we do here is overwrite the caller's AUTOLOAD subroutine  | 
| 
228
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # with our own.  | 
| 
229
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
230
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 Subroutines  | 
| 
231
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
232
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head2 import  | 
| 
233
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
234
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Called when the module is C | 
| 
235
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 subroutine into the caller's symbol table.  | 
| 
236
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
237
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =cut  | 
| 
238
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
239
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub import  {  | 
| 
240
 | 
24
 | 
 
 | 
 
 | 
  
24
  
 | 
 
 | 
12803
 | 
   my $class = shift;  | 
| 
241
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
242
 | 
17
 | 
 
 | 
 
 | 
  
17
  
 | 
 
 | 
136
 | 
   no strict 'refs'; # WARNING: Deep magic here!  | 
| 
 
 | 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
34
 | 
    | 
| 
 
 | 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
27667
 | 
    | 
| 
243
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
244
 | 
24
 | 
 
 | 
 
 | 
 
 | 
 
 | 
51
 | 
   my %param;  | 
| 
245
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   my %CONF;  | 
| 
246
 | 
24
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
131
 | 
   %param = @_ if @_;  | 
| 
247
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
248
 | 
24
 | 
 
 | 
 
 | 
 
 | 
 
 | 
85
 | 
   my %defaults = (  | 
| 
249
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     xform   => 'Text::Soundex',  | 
| 
250
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     match   => 'String::Equal',  | 
| 
251
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     choose  => 'Random',  | 
| 
252
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     suggest => 0,  | 
| 
253
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   );  | 
| 
254
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
255
 | 
24
 | 
 
 | 
 
 | 
 
 | 
 
 | 
110
 | 
   foreach (keys %param) {  | 
| 
256
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     SAS::Exception::InvalidParameter->throw(  | 
| 
257
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       error => "Invalid parameter $_\n",  | 
| 
258
 | 
32
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
159
 | 
     ) unless exists $defaults{$_};  | 
| 
259
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
260
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
261
 | 
23
 | 
 
 | 
 
 | 
 
 | 
 
 | 
85
 | 
   $CONF{xform}   = _set_transformer(\%param, $defaults{xform});  | 
| 
262
 | 
21
 | 
 
 | 
 
 | 
 
 | 
 
 | 
84
 | 
   $CONF{match}   = _set_matcher(\%param, $defaults{match});  | 
| 
263
 | 
19
 | 
 
 | 
 
 | 
 
 | 
 
 | 
68
 | 
   $CONF{choose}  =_set_chooser(\%param, $defaults{choose});  | 
| 
264
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
265
 | 
17
 | 
 
 | 
  
 66
  
 | 
 
 | 
 
 | 
131
 | 
   $CONF{suggest} = $param{suggest} // $defaults{suggest};  | 
| 
266
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
267
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # Now install appropriate AUTOLOAD routine in caller's package  | 
| 
268
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
269
 | 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
60
 | 
   my $pkg =  caller(0);  | 
| 
270
 | 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
135
 | 
   *{"${pkg}::AUTOLOAD"} = _make_AUTOLOAD(%CONF);  | 
| 
 
 | 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
21380
 | 
    | 
| 
271
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
272
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
273
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Work out which transformer(s) to use. The valid options are:  | 
| 
274
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # 1/ $param{xform} doesn't exist. Use default transformer.  | 
| 
275
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # 2/ $param{xform} is undef. Use no transformers.  | 
| 
276
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # 3/ $param{xform} is a reference to a subroutine. Use the  | 
| 
277
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #    referenced subroutine as the transformer.  | 
| 
278
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # 4/ $param{xform} is a scalar. This is the name of a transformer  | 
| 
279
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #    module which should be loaded.  | 
| 
280
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # 5/ $param{xform} is a reference to an array. Each element of the  | 
| 
281
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #    array is one of the previous two options.  | 
| 
282
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _set_transformer {  | 
| 
283
 | 
23
 | 
 
 | 
 
 | 
  
23
  
 | 
 
 | 
55
 | 
   my ($param, $default) = @_;  | 
| 
284
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
285
 | 
23
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
68
 | 
   unless (exists $param->{xform}) {  | 
| 
286
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
35
 | 
     my $mod = "Symbol::Approx::Sub::$default";  | 
| 
287
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
40
 | 
     load $mod;  | 
| 
288
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
340
 | 
     return [\&{"${mod}::transform"}];  | 
| 
 
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
60
 | 
    | 
| 
289
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
290
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
291
 | 
15
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
77
 | 
   unless (defined $param->{xform}) {  | 
| 
292
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
26
 | 
     return [];  | 
| 
293
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
294
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
295
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
24
 | 
   my $type = ref $param->{xform};  | 
| 
296
 | 
8
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
39
 | 
   if ($type eq 'CODE') {  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
297
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
     return [$param->{xform}];  | 
| 
298
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } elsif ($type eq '') {  | 
| 
299
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
     my $mod = "Symbol::Approx::Sub::$param->{xform}";  | 
| 
300
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
     load $mod;  | 
| 
301
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
36
 | 
     return [\&{"${mod}::transform"}];  | 
| 
 
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
25
 | 
    | 
| 
302
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } elsif ($type eq 'ARRAY') {  | 
| 
303
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
     my @xforms;  | 
| 
304
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
     foreach (@{$param->{xform}}) {  | 
| 
 
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
    | 
| 
305
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
       my $subtype = ref $_;  | 
| 
306
 | 
4
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
15
 | 
       if ($subtype eq 'CODE') {  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
307
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
         push @xforms, $_;  | 
| 
308
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       } elsif ($subtype eq '') {  | 
| 
309
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
         my $mod = "Symbol::Approx::Sub::$_";  | 
| 
310
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
         load $mod;  | 
| 
311
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
         push @xforms, \&{"${mod}::transform"};  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
    | 
| 
312
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       } else {  | 
| 
313
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
         SAS::Exception::InvalidOption::Transformer->throw(  | 
| 
314
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
           error => 'Invalid transformer passed to Symbol::Approx::Sub'  | 
| 
315
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         );  | 
| 
316
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
317
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
318
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
22
 | 
     return \@xforms;  | 
| 
319
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } else {  | 
| 
320
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
     SAS::Exception::InvalidOption::Transformer->throw(  | 
| 
321
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       error => 'Invalid transformer passed to Symbol::Approx::Sub'  | 
| 
322
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     );  | 
| 
323
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
324
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
325
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
326
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Work out which matcher to use. The valid options are:  | 
| 
327
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # 1/ $param{match} doesn't exist. Use default matcher.  | 
| 
328
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # 2/ $param{match} is undef. Use no matcher.  | 
| 
329
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # 3/ $param{match} is a reference to a subroutine. Use the  | 
| 
330
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #    referenced subroutine as the matcher.  | 
| 
331
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # 4/ $param{match} is a scalar. This is the name of a matcher  | 
| 
332
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #    module which should be loaded.  | 
| 
333
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _set_matcher {  | 
| 
334
 | 
21
 | 
 
 | 
 
 | 
  
21
  
 | 
 
 | 
54
 | 
   my ($param, $default) = @_;  | 
| 
335
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
336
 | 
21
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
427
 | 
   unless (exists $param->{match}) {  | 
| 
337
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
30
 | 
     my $mod = "Symbol::Approx::Sub::$default";  | 
| 
338
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
57
 | 
     load $mod;  | 
| 
339
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
245
 | 
     return \&{"${mod}::match"};  | 
| 
 
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
76
 | 
    | 
| 
340
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
341
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
342
 | 
10
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
32
 | 
   unless (defined $param->{match}) {  | 
| 
343
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
     return undef;  | 
| 
344
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
345
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
346
 | 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
23
 | 
   my $type = ref $param->{match};  | 
| 
347
 | 
9
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
32
 | 
   if ($type eq 'CODE') {  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
348
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
18
 | 
     return $param->{match};  | 
| 
349
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } elsif ($type eq '') {  | 
| 
350
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
     my $mod = "Symbol::Approx::Sub::$param->{match}";  | 
| 
351
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
     load $mod;  | 
| 
352
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
     return \&{"${mod}::match"};  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
    | 
| 
353
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } else {  | 
| 
354
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15
 | 
     SAS::Exception::InvalidOption::Matcher->throw(  | 
| 
355
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       error => 'Invalid matcher passed to Symbol::Approx::Sub'  | 
| 
356
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     );  | 
| 
357
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
358
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
359
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
360
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Work out which chooser to use. The valid options are:  | 
| 
361
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # 1/ $param{choose} doesn't exist. Use default chooser.  | 
| 
362
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # 2/ $param{choose} is undef. Use default chooser.  | 
| 
363
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # 3/ $param{choose} is a reference to a subroutine. Use the  | 
| 
364
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #    referenced subroutine as the chooser.  | 
| 
365
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # 4/ $param{choose} is a scalar. This is the name of a chooser  | 
| 
366
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #    module which should be loaded.  | 
| 
367
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _set_chooser {  | 
| 
368
 | 
19
 | 
 
 | 
 
 | 
  
19
  
 | 
 
 | 
51
 | 
   my ($param, $default) = @_;  | 
| 
369
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
370
 | 
19
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
69
 | 
   unless (exists $param->{choose}) {  | 
| 
371
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
41
 | 
     my $mod = "Symbol::Approx::Sub::$default";  | 
| 
372
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
70
 | 
     load $mod;  | 
| 
373
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
218
 | 
     return \&{"${mod}::choose"};  | 
| 
 
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
110
 | 
    | 
| 
374
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
375
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
376
 | 
5
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
13
 | 
   unless (defined $param->{choose}) {  | 
| 
377
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
     my $mod = "Symbol::Approx::Sub::$default";  | 
| 
378
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
     load $mod;  | 
| 
379
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
20
 | 
     return \&{"${mod}::choose"};  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
    | 
| 
380
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
381
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
382
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
   my $type = ref $param->{choose};  | 
| 
383
 | 
4
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
15
 | 
   if ($type eq 'CODE') {  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
384
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
     return $param->{choose};  | 
| 
385
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } elsif ($type eq '') {  | 
| 
386
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
     my $mod = "Symbol::Approx::Sub::$param->{choose}";  | 
| 
387
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
     load $mod;  | 
| 
388
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
67
 | 
     return \&{"${mod}::choose"};  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
    | 
| 
389
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } else {  | 
| 
390
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
16
 | 
     SAS::Exception::InvalidOption::Chooser->throw(  | 
| 
391
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       error => 'Invalid chooser passed to Symbol::Approx::Sub',  | 
| 
392
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     );  | 
| 
393
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
394
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
395
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
396
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _run_xformers {  | 
| 
397
 | 
27
 | 
 
 | 
 
 | 
  
27
  
 | 
 
 | 
182
 | 
   my ($xforms, $sub, @subs) = @_;  | 
| 
398
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
399
 | 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
123
 | 
   foreach (@$xforms) {  | 
| 
400
 | 
16
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
139
 | 
     SAS::Exception::InvalidOption::Transformer->throw(  | 
| 
401
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       error => 'Invalid transformer passed to Symbol::Approx::Sub',  | 
| 
402
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     ) unless defined &$_;  | 
| 
403
 | 
16
 | 
 
 | 
 
 | 
 
 | 
 
 | 
88
 | 
     ($sub, @subs) = $_->($sub, @subs);  | 
| 
404
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
405
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
406
 | 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
323
 | 
   return ($sub, @subs);  | 
| 
407
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
408
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
409
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _run_matcher {  | 
| 
410
 | 
27
 | 
 
 | 
 
 | 
  
27
  
 | 
 
 | 
146
 | 
   my ($matcher, $sub, @subs) = @_;  | 
| 
411
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
412
 | 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
50
 | 
   my @match_ind;  | 
| 
413
 | 
27
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
88
 | 
   if ($matcher) {  | 
| 
414
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     SAS::Exception::InvalidOption::Matcher->throw(  | 
| 
415
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       error => 'Invalid matcher passed to Symbol::Approx::Sub',  | 
| 
416
 | 
22
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
40
 | 
     ) unless defined &{$matcher};  | 
| 
 
 | 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
79
 | 
    | 
| 
417
 | 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
120
 | 
     @match_ind = $matcher->($sub, @subs);  | 
| 
418
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } else {  | 
| 
419
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
     @match_ind = (0 .. $#subs);  | 
| 
420
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
421
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
422
 | 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
270
 | 
   return @match_ind;  | 
| 
423
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
424
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
425
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _run_chooser {  | 
| 
426
 | 
8
 | 
 
 | 
 
 | 
  
8
  
 | 
 
 | 
28
 | 
   my ($chooser, @subs) = @_;  | 
| 
427
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
428
 | 
8
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
23
 | 
   SAS::Exception::InvalidOption::Chooser->throw(  | 
| 
429
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     error => 'Invalid chooser passed to Symbol::Approx::Sub'  | 
| 
430
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   ) unless defined &$chooser;  | 
| 
431
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
28
 | 
   my $index = $chooser->(@subs);  | 
| 
432
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
433
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
32
 | 
   return $index;  | 
| 
434
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
435
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
436
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Create a subroutine which is called when a given subroutine  | 
| 
437
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # name can't be found in the current package. In the import subroutine  | 
| 
438
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # above, we have already arranged that our calling package will use  | 
| 
439
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # the AUTOLOAD created here instead of its own.  | 
| 
440
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _make_AUTOLOAD {  | 
| 
441
 | 
17
 | 
 
 | 
 
 | 
  
17
  
 | 
 
 | 
71
 | 
   my %CONF = @_;  | 
| 
442
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
443
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   return sub {  | 
| 
444
 | 
27
 | 
 
 | 
 
 | 
  
27
  
 | 
 
 | 
6598
 | 
     my @c = caller(0);  | 
| 
445
 | 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
429
 | 
     my ($pkg, $sub) = $AUTOLOAD =~ /^(.*)::(.*)$/;  | 
| 
446
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
447
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Get a list of all of the subroutines in the current package  | 
| 
448
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # using the get_subs function from GlobWalker.pm  | 
| 
449
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Note that we deliberately omit function names that exist  | 
| 
450
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # in the %_BARRED hash  | 
| 
451
 | 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
74
 | 
     my (@subs, @orig);  | 
| 
452
 | 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
34068
 | 
     my $sym = Devel::Symdump->new($pkg);  | 
| 
453
 | 
550
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1152
 | 
     @orig = @subs = grep { ! $_BARRED{$_} }  | 
| 
454
 | 
550
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1407
 | 
                     map { s/${pkg}:://; $_ }  | 
| 
 
 | 
550
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1033
 | 
    | 
| 
455
 | 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1645
 | 
                     grep { defined &{$_} } $sym->functions();  | 
| 
 
 | 
567
 | 
 
 | 
 
 | 
 
 | 
 
 | 
760
 | 
    | 
| 
 
 | 
567
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1257
 | 
    | 
| 
456
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
457
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Transform all of the subroutine names  | 
| 
458
 | 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
220
 | 
     ($sub, @subs) = _run_xformers($CONF{xform}, $sub, @subs);  | 
| 
459
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
460
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Call the subroutine that will look for matches  | 
| 
461
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # The matcher returns a list of the _indexes_ that match  | 
| 
462
 | 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
149
 | 
     my @match_ind = _run_matcher($CONF{match}, $sub, @subs);  | 
| 
463
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
464
 | 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
102
 | 
     @subs = @subs[@match_ind];  | 
| 
465
 | 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
98
 | 
     @orig = @orig[@match_ind];  | 
| 
466
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
467
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # If we've got more than one matched subroutine, then call the  | 
| 
468
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # chooser to pick one.  | 
| 
469
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Call the matched subroutine using magic goto.  | 
| 
470
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # If no match was found, die recreating Perl's usual behaviour.  | 
| 
471
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
472
 | 
27
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
174
 | 
     die "REALLY Undefined subroutine $AUTOLOAD called at $c[1] line $c[2]\n"  | 
| 
473
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       unless @match_ind;  | 
| 
474
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
475
 | 
25
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
97
 | 
     if (@match_ind == 1) {  | 
| 
476
 | 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
61
 | 
       $sub = "${pkg}::" . $orig[0];  | 
| 
477
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
478
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
74
 | 
       my $index = _run_chooser($CONF{choose}, @subs);  | 
| 
479
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
27
 | 
       $sub = "${pkg}::" . $orig[$index];  | 
| 
480
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
481
 | 
25
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
80
 | 
     if ($CONF{suggest}) {  | 
| 
482
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
21
 | 
       croak "Cannot find subroutine $AUTOLOAD. Did you mean $sub?";  | 
| 
483
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
484
 | 
24
 | 
 
 | 
 
 | 
 
 | 
 
 | 
731
 | 
       goto &$sub;  | 
| 
485
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
486
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
487
 | 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
111
 | 
 }  | 
| 
488
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
489
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 1;  | 
| 
490
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 __END__  |