| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Acme::Sub::Parms; |
|
2
|
|
|
|
|
|
|
|
|
3
|
4
|
|
|
4
|
|
7530
|
use strict; |
|
|
4
|
|
|
|
|
23
|
|
|
|
4
|
|
|
|
|
114
|
|
|
4
|
4
|
|
|
4
|
|
18
|
use warnings; |
|
|
4
|
|
|
|
|
8
|
|
|
|
4
|
|
|
|
|
106
|
|
|
5
|
4
|
|
|
4
|
|
2222
|
use Filter::Util::Call; |
|
|
4
|
|
|
|
|
4066
|
|
|
|
4
|
|
|
|
|
404
|
|
|
6
|
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
BEGIN { |
|
8
|
4
|
|
|
4
|
|
15
|
$Acme::Sub::Parms::VERSION = '1.03'; |
|
9
|
4
|
|
|
|
|
7
|
%Acme::Sub::Parms::args = (); |
|
10
|
4
|
|
|
|
|
15
|
%Acme::Sub::Parms::raw_args = (); |
|
11
|
4
|
|
|
|
|
12179
|
$Acme::Sub::Parms::line_counter = 0; |
|
12
|
|
|
|
|
|
|
} |
|
13
|
|
|
|
|
|
|
|
|
14
|
445
|
|
|
445
|
|
644
|
sub _NORMALIZE () { return ':normalize'; }; |
|
15
|
473
|
|
|
473
|
|
582
|
sub _NO_VALIDATION () { return ':no_validation'; }; |
|
16
|
445
|
|
|
445
|
|
834
|
sub _DUMP () { return ':dump_to_stdout'; }; |
|
17
|
|
|
|
|
|
|
sub _DEBUG () { 0; }; |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
sub _legal_option { |
|
20
|
|
|
|
|
|
|
return { |
|
21
|
|
|
|
|
|
|
_NORMALIZE() => 1, |
|
22
|
|
|
|
|
|
|
_NO_VALIDATION() => 1, |
|
23
|
|
|
|
|
|
|
_DUMP() => 1, |
|
24
|
5
|
|
|
5
|
|
7
|
}->{$_[0]}; |
|
25
|
|
|
|
|
|
|
} |
|
26
|
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
#### |
|
28
|
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
sub import { |
|
30
|
4
|
|
|
4
|
|
41
|
my $class = shift; |
|
31
|
4
|
|
|
|
|
13
|
my $options = { |
|
32
|
|
|
|
|
|
|
_NORMALIZE() => 0, |
|
33
|
|
|
|
|
|
|
_NO_VALIDATION() => 0, |
|
34
|
|
|
|
|
|
|
_DUMP() => 0, |
|
35
|
|
|
|
|
|
|
}; |
|
36
|
4
|
|
|
|
|
15
|
foreach my $item (@_) { |
|
37
|
5
|
50
|
|
|
|
11
|
if (not _legal_option($item)) { |
|
38
|
0
|
|
|
|
|
0
|
my $package = __PACKAGE__; |
|
39
|
0
|
|
|
|
|
0
|
require Carp; |
|
40
|
0
|
|
|
|
|
0
|
Carp::croak("'$item' not a valid option for 'use $package'\n"); |
|
41
|
|
|
|
|
|
|
} |
|
42
|
5
|
|
|
|
|
13
|
$options->{$item} = 1; |
|
43
|
|
|
|
|
|
|
} |
|
44
|
4
|
|
|
|
|
10
|
$Acme::Sub::Parms::line_counter = 0; |
|
45
|
4
|
|
|
|
|
9
|
my $ref = {'options' => $options, 'bind_block' => 0 }; |
|
46
|
4
|
|
|
|
|
13
|
filter_add(bless $ref); # imported from Filter::Util::Call |
|
47
|
|
|
|
|
|
|
} |
|
48
|
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
#### |
|
50
|
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
sub _parse_bind_spec { |
|
52
|
28
|
|
|
28
|
|
40
|
my ($self, $raw_spec) = @_; |
|
53
|
|
|
|
|
|
|
|
|
54
|
28
|
|
|
|
|
36
|
my $spec = $raw_spec; |
|
55
|
|
|
|
|
|
|
|
|
56
|
28
|
|
|
|
|
62
|
my $spec_tokens = { |
|
57
|
|
|
|
|
|
|
'is_defined' => 0, |
|
58
|
|
|
|
|
|
|
'required' => 1, |
|
59
|
|
|
|
|
|
|
'optional' => 0, |
|
60
|
|
|
|
|
|
|
}; |
|
61
|
28
|
|
|
|
|
66
|
while ($spec ne '') { |
|
62
|
56
|
100
|
|
|
|
291
|
if ($spec =~ s/^required(\s*,\s*|$)//) { # 'required' flag |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
63
|
8
|
|
|
|
|
13
|
$spec_tokens->{'required'} = 1; |
|
64
|
8
|
|
|
|
|
16
|
$spec_tokens->{'optional'} = 0; |
|
65
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
} elsif ($spec =~ s/^optional(\s*,\s*|$)//) { # 'optional' flag |
|
67
|
16
|
|
|
|
|
36
|
$spec_tokens->{'required'} = 0; |
|
68
|
16
|
|
|
|
|
32
|
$spec_tokens->{'optional'} = 1; |
|
69
|
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
} elsif ($spec =~ s/^is_defined(\s*,\s*|$)//) { # 'is_defined' flag |
|
71
|
8
|
|
|
|
|
18
|
$spec_tokens->{'is_defined'} = 1; |
|
72
|
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
} elsif ($spec =~ s/^(can|isa|type|callback|default)\s*=\s*//) { # 'something="somevalue"' |
|
74
|
24
|
|
|
|
|
53
|
my $spec_key = $1; |
|
75
|
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
# Simple unquoted text with no embedded ws |
|
77
|
24
|
100
|
|
|
|
128
|
if ($spec =~ s/^([^\s"',]+)(\s*,\s*|$)//) { |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
78
|
20
|
|
|
|
|
67
|
$spec_tokens->{$spec_key} = $1; |
|
79
|
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
# Single quoted text with no embedded quotes |
|
81
|
|
|
|
|
|
|
} elsif ($spec =~ s/^'([^'\/]+)'\s*,\s*//) { |
|
82
|
0
|
|
|
|
|
0
|
$spec_tokens->{$spec_key} = "'$1'"; |
|
83
|
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
# Double quoted text with no embedded quotes or escapes |
|
85
|
|
|
|
|
|
|
} elsif ($spec =~ s/^"([^"\/]+)"\s*,\s*//) { |
|
86
|
0
|
|
|
|
|
0
|
$spec_tokens->{$spec_key} = '"' . $1 . '"'; |
|
87
|
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
# It is a tricky case with quoted characters. One character at a time it is. |
|
89
|
|
|
|
|
|
|
} elsif ($spec =~ s/^(['"])//) { |
|
90
|
4
|
|
|
|
|
10
|
my $quote = $1; |
|
91
|
4
|
|
|
|
|
8
|
my $upend_spec = reverse $spec; |
|
92
|
4
|
|
|
|
|
8
|
my $block_done = 0; |
|
93
|
4
|
|
|
|
|
4
|
my $escape_next = 0; |
|
94
|
4
|
|
|
|
|
8
|
my $token = $quote; |
|
95
|
4
|
|
66
|
|
|
50
|
until ($block_done || ($upend_spec eq '')) { |
|
96
|
32
|
|
|
|
|
61
|
my $ch = chop $upend_spec; |
|
97
|
32
|
50
|
33
|
|
|
88
|
if ($escape_next) { |
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
98
|
0
|
|
|
|
|
0
|
$token .= $ch; |
|
99
|
0
|
|
|
|
|
0
|
$escape_next = 0; |
|
100
|
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
} elsif (($ch eq "\\") && (not $escape_next)) { |
|
102
|
0
|
|
|
|
|
0
|
$token .= $ch; |
|
103
|
0
|
|
|
|
|
0
|
$escape_next = 1; |
|
104
|
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
} elsif ($ch eq $quote) { |
|
106
|
4
|
|
|
|
|
12
|
$block_done = 1; |
|
107
|
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
} else { |
|
109
|
28
|
|
|
|
|
74
|
$token .= $ch; |
|
110
|
|
|
|
|
|
|
} |
|
111
|
|
|
|
|
|
|
} |
|
112
|
4
|
50
|
|
|
|
10
|
if ($escape_next) { |
|
113
|
0
|
|
|
|
|
0
|
die("Syntax error in BindParms spec: $raw_spec\n"); |
|
114
|
|
|
|
|
|
|
} |
|
115
|
4
|
|
|
|
|
8
|
$spec = reverse $upend_spec; |
|
116
|
4
|
|
|
|
|
25
|
$spec_tokens->{$spec_key} = $token . $quote; |
|
117
|
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
} else { |
|
119
|
0
|
|
|
|
|
0
|
die("Syntax error in BindParms spec: $raw_spec\n"); |
|
120
|
|
|
|
|
|
|
} |
|
121
|
|
|
|
|
|
|
} else { |
|
122
|
0
|
|
|
|
|
0
|
die("Syntax error in BindParms spec: $raw_spec\n"); |
|
123
|
|
|
|
|
|
|
} |
|
124
|
|
|
|
|
|
|
} |
|
125
|
28
|
|
|
|
|
57
|
return $spec_tokens; |
|
126
|
|
|
|
|
|
|
} |
|
127
|
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
############################################################################### |
|
129
|
|
|
|
|
|
|
# bind_spec is intentionally a a non-POD documented'public' method. It can be overridden in a sub-class |
|
130
|
|
|
|
|
|
|
# to provide alternative features. |
|
131
|
|
|
|
|
|
|
# |
|
132
|
|
|
|
|
|
|
# It takes two parameters: |
|
133
|
|
|
|
|
|
|
# |
|
134
|
|
|
|
|
|
|
# $raw_spec - this is the content of the [....] block (not including the '[' and ']' block delimitters) |
|
135
|
|
|
|
|
|
|
# $field_name - the hash key for the field being processed |
|
136
|
|
|
|
|
|
|
# |
|
137
|
|
|
|
|
|
|
# As each line of the BindParms block is processed the two parameters for each line are passed to the bind_spec |
|
138
|
|
|
|
|
|
|
# method for evaluation. bind_spec should return a string containing any Perl code generated as a result of |
|
139
|
|
|
|
|
|
|
# the bind specification. |
|
140
|
|
|
|
|
|
|
# |
|
141
|
|
|
|
|
|
|
# Good style dictates that the returned output should be *ONE* line (it could be a very *long* line) |
|
142
|
|
|
|
|
|
|
# so that line numbering in the source file is preserved for any error messages. |
|
143
|
|
|
|
|
|
|
# |
|
144
|
|
|
|
|
|
|
sub bind_spec { |
|
145
|
28
|
|
|
28
|
0
|
34
|
my $self = shift; |
|
146
|
28
|
|
|
|
|
43
|
my ($raw_spec, $field_name) = @_; |
|
147
|
|
|
|
|
|
|
|
|
148
|
28
|
|
|
|
|
36
|
my $options = $self->{'options'}; |
|
149
|
28
|
|
|
|
|
42
|
my $no_validation = $options->{_NO_VALIDATION()}; |
|
150
|
|
|
|
|
|
|
|
|
151
|
28
|
|
|
|
|
187
|
my $spec_tokens = $self->_parse_bind_spec($raw_spec); |
|
152
|
|
|
|
|
|
|
|
|
153
|
28
|
|
|
|
|
34
|
my $has_side_effects = 0; |
|
154
|
28
|
|
|
|
|
32
|
my $output = ''; |
|
155
|
|
|
|
|
|
|
|
|
156
|
28
|
|
|
|
|
93
|
my @spec_tokens_list = keys %$spec_tokens; |
|
157
|
28
|
0
|
33
|
|
|
89
|
if ((0 == @spec_tokens_list) || ((1 == @spec_tokens_list) && ($spec_tokens->{'optional'}))) { |
|
|
|
|
33
|
|
|
|
|
|
158
|
0
|
|
|
|
|
0
|
return; |
|
159
|
|
|
|
|
|
|
} |
|
160
|
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
###################### |
|
162
|
|
|
|
|
|
|
# default="some value" |
|
163
|
28
|
100
|
|
|
|
56
|
if (defined $spec_tokens->{'default'}) { |
|
164
|
4
|
50
|
|
|
|
12
|
if ($spec_tokens->{'optional'}) { |
|
165
|
4
|
|
|
|
|
30
|
$output .= "unless (exists (\$Acme::Sub::Parms::args\{'$field_name'\})) \{ \$Acme::Sub::Parms::args\{'$field_name'\} = " . $spec_tokens->{'default'} . ";\} "; |
|
166
|
|
|
|
|
|
|
} else { # required |
|
167
|
0
|
|
|
|
|
0
|
$output .= "unless (defined (\$Acme::Sub::Parms::args\{'$field_name'\})) \{ \$Acme::Sub::Parms::args\{'$field_name'\} = " . $spec_tokens->{'default'} . ";\} "; |
|
168
|
|
|
|
|
|
|
} |
|
169
|
4
|
|
|
|
|
8
|
$has_side_effects = 1; |
|
170
|
|
|
|
|
|
|
} |
|
171
|
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
###################### |
|
173
|
|
|
|
|
|
|
# callback="some_subroutine" |
|
174
|
28
|
100
|
|
|
|
45
|
if ($spec_tokens->{'callback'}) { |
|
175
|
|
|
|
|
|
|
$output .= "\{ my (\$callback_is_valid, \$callback_error) = " |
|
176
|
8
|
|
|
|
|
59
|
. $spec_tokens->{'callback'} |
|
177
|
|
|
|
|
|
|
. "(\'$field_name\', \$Acme::Sub::Parms::args\{\'$field_name\'\}, \\\%Acme::Sub::Parms::args);" |
|
178
|
|
|
|
|
|
|
. "unless (\$callback_is_valid) { require Carp; Carp::croak(\"$field_name error: \$callback_error\"); }} "; |
|
179
|
8
|
|
|
|
|
14
|
$has_side_effects = 1; |
|
180
|
|
|
|
|
|
|
} |
|
181
|
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
###################### |
|
183
|
|
|
|
|
|
|
# required |
|
184
|
28
|
100
|
100
|
|
|
89
|
if ((! $no_validation) && $spec_tokens->{'required'}) { |
|
185
|
4
|
|
|
|
|
20
|
$output .= "unless (exists (\$Acme::Sub::Parms::args\{\'$field_name\'\})) { require Carp; Carp::croak(\"Missing required parameter \'$field_name\'\"); } "; |
|
186
|
|
|
|
|
|
|
} |
|
187
|
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
###################### |
|
189
|
|
|
|
|
|
|
# is_defined |
|
190
|
28
|
100
|
|
|
|
47
|
if ($spec_tokens->{'is_defined'}) { |
|
191
|
8
|
|
|
|
|
29
|
$output .= "if (exists (\$Acme::Sub::Parms::args\{\'$field_name\'\}) and (! defined (\$Acme::Sub::Parms::args\{\'$field_name\'\}))) { require Carp; Carp::croak(\"parameter \'$field_name\' cannot be undef\"); } "; |
|
192
|
|
|
|
|
|
|
} |
|
193
|
|
|
|
|
|
|
|
|
194
|
28
|
|
|
|
|
36
|
my $type_requirements = $spec_tokens->{'type'}; |
|
195
|
28
|
|
|
|
|
37
|
my $isa_requirements = $spec_tokens->{'isa'}; |
|
196
|
28
|
|
|
|
|
30
|
my $can_requirements = $spec_tokens->{'can'}; |
|
197
|
|
|
|
|
|
|
|
|
198
|
28
|
100
|
100
|
|
|
118
|
if (defined ($type_requirements ) || defined($isa_requirements) || defined($can_requirements)) { |
|
|
|
|
100
|
|
|
|
|
|
199
|
12
|
|
|
|
|
37
|
$output .= "if (exists (\$Acme::Sub::Parms::args\{\'$field_name\'\})) \{"; |
|
200
|
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
##################### |
|
202
|
|
|
|
|
|
|
# type="SomeRefType" or type="SomeRefType, SomeOtherRefType, ..." |
|
203
|
12
|
100
|
|
|
|
25
|
if (defined $type_requirements) { |
|
204
|
4
|
|
|
|
|
9
|
$type_requirements =~ s/^['"]//; |
|
205
|
4
|
|
|
|
|
8
|
$type_requirements =~ s/['"]$//; |
|
206
|
4
|
|
|
|
|
11
|
my @type_classes = split(/[,\s]+/, $type_requirements); |
|
207
|
4
|
|
|
|
|
15
|
$output .= "unless ("; |
|
208
|
4
|
|
|
|
|
8
|
my @type_tests = (); |
|
209
|
4
|
|
|
|
|
6
|
foreach my $class_name (@type_classes) { |
|
210
|
4
|
|
|
|
|
14
|
push (@type_tests, "ref(\$Acme::Sub::Parms::args\{'$field_name'\}) eq '$class_name')"); |
|
211
|
|
|
|
|
|
|
} |
|
212
|
4
|
|
|
|
|
19
|
$output .= join(' || ',@type_tests) . " \{ require Carp; Carp::croak(\'parameter \\\'$field_name\\\' must be a " . join(' or ',@type_classes) . "\'); \}"; |
|
213
|
|
|
|
|
|
|
} |
|
214
|
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
##################### |
|
216
|
|
|
|
|
|
|
# isa="SomeRefType" or isa="SomeRefType, SomeOtherRefType, ..." |
|
217
|
12
|
100
|
|
|
|
34
|
if (defined $isa_requirements) { |
|
218
|
4
|
|
|
|
|
17
|
$isa_requirements =~ s/^['"]//; |
|
219
|
4
|
|
|
|
|
9
|
$isa_requirements =~ s/['"]$//; |
|
220
|
4
|
|
|
|
|
15
|
my @isa_classes = split(/[,\s]+/, $isa_requirements); |
|
221
|
4
|
|
|
|
|
8
|
$output .= "unless ("; |
|
222
|
4
|
|
|
|
|
8
|
my @isa_tests = (); |
|
223
|
4
|
|
|
|
|
7
|
foreach my $class_name (@isa_classes) { |
|
224
|
4
|
|
|
|
|
23
|
push (@isa_tests, "\$Acme::Sub::Parms::args\{'$field_name'\}->isa('$class_name')"); |
|
225
|
|
|
|
|
|
|
} |
|
226
|
4
|
|
|
|
|
21
|
$output .= join(' || ',@isa_tests) . ") \{ require Carp; Carp::croak(\'parameter \\\'$field_name\\\' must be a " . join(' or ',@isa_classes) . " instance or subclass\'); \}"; |
|
227
|
|
|
|
|
|
|
} |
|
228
|
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
##################### |
|
230
|
|
|
|
|
|
|
# can="somemethod" or can="somemethod, someothermethod, ..." |
|
231
|
12
|
100
|
|
|
|
39
|
if (defined $can_requirements) { |
|
232
|
4
|
|
|
|
|
13
|
$can_requirements =~ s/^['"]//; |
|
233
|
4
|
|
|
|
|
18
|
$can_requirements =~ s/['"]$//; |
|
234
|
4
|
|
|
|
|
22
|
my @can_methods = split(/[,\s]+/, $can_requirements); |
|
235
|
4
|
|
|
|
|
35
|
$output .= "unless ("; |
|
236
|
4
|
|
|
|
|
17
|
my @can_tests = (); |
|
237
|
4
|
|
|
|
|
8
|
foreach my $method_name (@can_methods) { |
|
238
|
4
|
|
|
|
|
15
|
push (@can_tests, "\$Acme::Sub::Parms::args\{'$field_name'\}->can('$method_name')"); |
|
239
|
|
|
|
|
|
|
} |
|
240
|
4
|
|
|
|
|
28
|
$output .= join(' && ',@can_tests) . ") \{ require Carp; Carp::croak(\'parameter \\\'$field_name\\\' must be an object with a " . join(' and a ',@can_methods) . " method\'); \}"; |
|
241
|
|
|
|
|
|
|
} |
|
242
|
|
|
|
|
|
|
|
|
243
|
12
|
|
|
|
|
19
|
$output .= "\}"; |
|
244
|
|
|
|
|
|
|
} |
|
245
|
|
|
|
|
|
|
|
|
246
|
28
|
|
|
|
|
132
|
return ($has_side_effects,$output); |
|
247
|
|
|
|
|
|
|
} |
|
248
|
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
#### |
|
250
|
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
sub filter { |
|
252
|
436
|
|
|
436
|
0
|
803
|
my $self = shift; |
|
253
|
|
|
|
|
|
|
|
|
254
|
436
|
|
|
|
|
518
|
my $options = $self->{'options'}; |
|
255
|
436
|
|
|
|
|
597
|
my $dump_to_stdout = $options->{_DUMP()}; |
|
256
|
436
|
|
|
|
|
570
|
my $normalize = $options->{_NORMALIZE()}; |
|
257
|
436
|
|
|
|
|
522
|
my $no_validation = $options->{_NO_VALIDATION()}; |
|
258
|
436
|
|
|
|
|
464
|
my $bind_block = $self->{'bind_block'}; |
|
259
|
|
|
|
|
|
|
|
|
260
|
436
|
|
|
|
|
422
|
my $status; |
|
261
|
|
|
|
|
|
|
|
|
262
|
436
|
100
|
|
|
|
1430
|
if ($status = filter_read() > 0) { # imported from Filter::Util::Call |
|
263
|
432
|
|
|
|
|
485
|
$Acme::Sub::Parms::line_counter++; |
|
264
|
|
|
|
|
|
|
|
|
265
|
432
|
|
|
|
|
390
|
if (_DEBUG) { |
|
266
|
|
|
|
|
|
|
print STDERR "input line $Acme::Sub::Parms::line_counter: $_"; |
|
267
|
|
|
|
|
|
|
} |
|
268
|
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
############################################# |
|
270
|
|
|
|
|
|
|
# If we are in a bind block, handle it |
|
271
|
432
|
100
|
|
|
|
539
|
if ($bind_block) { |
|
272
|
36
|
|
|
|
|
46
|
my $bind_entries = $self->{'bind_entries'}; |
|
273
|
36
|
|
|
|
|
37
|
my $simple_bind = $self->{'simple_bind'}; |
|
274
|
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
############################## |
|
276
|
|
|
|
|
|
|
# Last line of the bind block? Generate the working code. |
|
277
|
36
|
100
|
|
|
|
373
|
if (m/^\s*\)(\s*$|\s*#.*$)/) { |
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
|
|
279
|
4
|
|
|
|
|
10
|
my $block_trailing_comment = $2; |
|
280
|
4
|
50
|
|
|
|
13
|
$block_trailing_comment = defined($block_trailing_comment) ? $block_trailing_comment : ''; |
|
281
|
4
|
|
|
|
|
8
|
$block_trailing_comment =~ s/[\r\n]+$//s; |
|
282
|
4
|
|
|
|
|
22
|
my $side_effects = 0; |
|
283
|
4
|
|
|
|
|
7
|
my $args = 'local %Acme::Sub::Parms::args; '; # needed? |
|
284
|
4
|
100
|
|
|
|
10
|
if ($normalize) { |
|
285
|
2
|
|
|
|
|
6
|
$args .= '{ local $_; local %Acme::Sub::Parms::raw_args = @_; %Acme::Sub::Parms::args = map { lc($_) => $Acme::Sub::Parms::raw_args{$_} } keys %Acme::Sub::Parms::raw_args; }' . "\n"; |
|
286
|
|
|
|
|
|
|
} else { |
|
287
|
2
|
|
|
|
|
7
|
$args .= '%Acme::Sub::Parms::args = @_;' . "\n"; |
|
288
|
|
|
|
|
|
|
} |
|
289
|
|
|
|
|
|
|
# If we have validation or defaults, handle them |
|
290
|
4
|
|
|
|
|
4
|
my $padding_lines = 0; |
|
291
|
4
|
50
|
|
|
|
12
|
if (! $simple_bind) { |
|
292
|
4
|
|
|
|
|
9
|
my @parm_declarations = (); |
|
293
|
4
|
|
|
|
|
9
|
foreach my $entry (@$bind_entries) { |
|
294
|
32
|
|
|
|
|
49
|
my $variable_decl = $entry->{'variable'}; |
|
295
|
32
|
|
|
|
|
41
|
my $field_name = $entry->{'field'}; |
|
296
|
32
|
|
|
|
|
34
|
my $spec = $entry->{'spec'}; |
|
297
|
32
|
|
|
|
|
39
|
my $trailing_comment = $entry->{'trailing_comment'}; |
|
298
|
32
|
100
|
66
|
|
|
129
|
if ( (! defined($spec)) || ($spec eq '')) { |
|
299
|
|
|
|
|
|
|
# push(@parm_declarations, $trailing_comment); |
|
300
|
4
|
|
|
|
|
11
|
next; |
|
301
|
|
|
|
|
|
|
} |
|
302
|
|
|
|
|
|
|
# The hard case. We have validation requirements. |
|
303
|
28
|
|
|
|
|
61
|
my ($has_side_effects, $bind_spec_output) = $self->bind_spec($spec, $field_name); |
|
304
|
28
|
|
|
|
|
40
|
$side_effects += $has_side_effects; |
|
305
|
28
|
|
|
|
|
90
|
push (@parm_declarations, "$bind_spec_output$trailing_comment"); |
|
306
|
|
|
|
|
|
|
} |
|
307
|
4
|
|
|
|
|
58
|
$args .= join("\n",@parm_declarations,''); |
|
308
|
|
|
|
|
|
|
} |
|
309
|
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
# Generate the actual parameter data binding |
|
311
|
4
|
|
|
|
|
12
|
my @var_declarations = (); |
|
312
|
4
|
|
|
|
|
6
|
my @hard_var_declarations = (); |
|
313
|
4
|
|
|
|
|
8
|
my @field_declarations = (); |
|
314
|
4
|
|
|
|
|
5
|
my @fields_list = (); |
|
315
|
4
|
|
|
|
|
8
|
foreach my $entry (@$bind_entries) { |
|
316
|
32
|
|
|
|
|
43
|
my $spec = $entry->{'spec'}; |
|
317
|
32
|
100
|
66
|
|
|
122
|
next if ((not defined $spec) || ($spec eq '')); |
|
318
|
28
|
|
|
|
|
35
|
my $raw_var = $entry->{'variable'}; |
|
319
|
28
|
|
|
|
|
34
|
my $field_name = $entry->{'field'}; |
|
320
|
|
|
|
|
|
|
|
|
321
|
28
|
|
|
|
|
57
|
push (@fields_list, "'$field_name'"); |
|
322
|
28
|
|
|
|
|
110
|
my ($variable_name) = $raw_var =~ m/^my\s+(\S+)$/; |
|
323
|
28
|
50
|
|
|
|
53
|
if (defined $variable_name) { # simple 'my $variable :' entries are special-cased for performance |
|
324
|
28
|
|
|
|
|
33
|
push (@var_declarations, $variable_name); |
|
325
|
28
|
|
|
|
|
61
|
push (@field_declarations, "'$field_name'"); |
|
326
|
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
} else { # Otherwise make a seperate entry for this binding |
|
328
|
0
|
|
|
|
|
0
|
push (@hard_var_declarations, "$raw_var = \$Acme::Sub::Parms::args\{$field_name\};"); |
|
329
|
|
|
|
|
|
|
} |
|
330
|
|
|
|
|
|
|
} |
|
331
|
4
|
|
|
|
|
17
|
my $hard_args = join(' ',@hard_var_declarations); |
|
332
|
4
|
|
|
|
|
6
|
my $arg_line = ''; |
|
333
|
4
|
50
|
|
|
|
44
|
if (0 < @var_declarations) { |
|
334
|
|
|
|
|
|
|
|
|
335
|
4
|
50
|
33
|
|
|
60
|
if ($simple_bind && (! $normalize) && $no_validation && (0 == $side_effects) && (0 == @hard_var_declarations)) { |
|
|
|
|
33
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
336
|
0
|
|
|
|
|
0
|
$args = "\n my (" . join(",", @var_declarations) . ') = @{{@_}}{' . join(',',@field_declarations) . '}; '; |
|
337
|
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
} else { |
|
339
|
|
|
|
|
|
|
|
|
340
|
4
|
|
|
|
|
52
|
$arg_line = 'my (' . join(",", @var_declarations) . ') = @Acme::Sub::Parms::args{' . join(',',@field_declarations) . '}; '; |
|
341
|
|
|
|
|
|
|
} |
|
342
|
|
|
|
|
|
|
} |
|
343
|
4
|
|
|
|
|
11
|
my $unknown_parms_check = ''; |
|
344
|
4
|
100
|
|
|
|
13
|
unless ($no_validation) { |
|
345
|
2
|
|
|
|
|
13
|
$unknown_parms_check = 'delete @Acme::Sub::Parms::args{' . join(',',@fields_list) . '}; if (0 < @Acme::Sub::Parms::args) { require Carp; Carp::croak(\'Unexpected parameters passed: \' . join(\', \',@Acme::Sub::Parms::args)); } '; |
|
346
|
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
} |
|
348
|
4
|
|
|
|
|
10
|
$self->{'bind_block'} = 0; |
|
349
|
4
|
|
|
|
|
8
|
my $original_block_length = $Acme::Sub::Parms::line_counter - $self->{'line_block_start'}; |
|
350
|
4
|
|
|
|
|
43
|
my $new_block = $args . join(' ',$arg_line, $hard_args, $unknown_parms_check) . "$block_trailing_comment\n"; |
|
351
|
4
|
|
|
|
|
65
|
$new_block =~ s/\n+/\n/gs; |
|
352
|
4
|
|
|
|
|
19
|
my $new_block_lines = $new_block =~ m/\n/gs; |
|
353
|
|
|
|
|
|
|
|
|
354
|
4
|
|
|
|
|
8
|
my $additional_lines = $original_block_length - $new_block_lines; |
|
355
|
|
|
|
|
|
|
#warn("Need $additional_lines extra lines\n---\n$new_block---\n"); |
|
356
|
4
|
50
|
|
|
|
23
|
if ($additional_lines > 0) { |
|
357
|
4
|
|
|
|
|
65
|
$_ = $new_block . ("\n" x $additional_lines); |
|
358
|
|
|
|
|
|
|
} else { |
|
359
|
0
|
|
|
|
|
0
|
$_ = $new_block; |
|
360
|
|
|
|
|
|
|
} |
|
361
|
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
######################## |
|
363
|
|
|
|
|
|
|
# Bind block parameter line |
|
364
|
|
|
|
|
|
|
} elsif (my($bind_var, $bind_field,$trailing_comment) = m/^\s*(\S.*?)\s+:\s+([^'"\s\[]+.*?)\s*(;\s*|;\s*#.*)$/) { |
|
365
|
28
|
50
|
|
|
|
72
|
$trailing_comment = defined($trailing_comment) ? $trailing_comment : ''; |
|
366
|
28
|
|
|
|
|
90
|
$trailing_comment =~ s/[\r\n]+$//s; |
|
367
|
28
|
|
|
|
|
64
|
$trailing_comment =~ s/^;//; |
|
368
|
28
|
|
|
|
|
110
|
my $bind_entry = { 'variable' => $bind_var, 'field' => $bind_field, trailing_comment => $trailing_comment }; |
|
369
|
28
|
|
|
|
|
50
|
push (@$bind_entries, $bind_entry); |
|
370
|
28
|
50
|
|
|
|
88
|
if ($bind_var !~ m/^my \$\S+$/) { |
|
371
|
0
|
|
|
|
|
0
|
$self->{'simple_bind'} = 0; |
|
372
|
|
|
|
|
|
|
} |
|
373
|
28
|
100
|
|
|
|
97
|
if ($bind_field =~ m/^(\S+)\s*\[(.*)\]$/) { # Complex spec |
|
|
|
50
|
|
|
|
|
|
|
374
|
26
|
|
|
|
|
62
|
$bind_entry->{'field'} = $1; |
|
375
|
26
|
|
|
|
|
68
|
$bind_entry->{'spec'} = $2; |
|
376
|
26
|
100
|
100
|
|
|
119
|
unless ($no_validation && ($bind_field !~ m/[\s\[,](default|callback)\s*=\s*/)) { |
|
377
|
18
|
|
|
|
|
26
|
$self->{'simple_bind'} = 0; |
|
378
|
|
|
|
|
|
|
} |
|
379
|
|
|
|
|
|
|
} elsif ($bind_field =~ m/^\w+$/) { # my $thing : something; |
|
380
|
2
|
|
|
|
|
4
|
$bind_entry->{'spec'} = 'required'; |
|
381
|
2
|
50
|
|
|
|
7
|
unless ($no_validation) { |
|
382
|
0
|
|
|
|
|
0
|
$self->{'simple_bind'} = 0; |
|
383
|
|
|
|
|
|
|
} |
|
384
|
|
|
|
|
|
|
} else { |
|
385
|
0
|
|
|
|
|
0
|
die("Failed to parse BindParms block line $Acme::Sub::Parms::line_counter: $_"); |
|
386
|
|
|
|
|
|
|
} |
|
387
|
28
|
|
|
|
|
53
|
undef $trailing_comment; |
|
388
|
28
|
|
|
|
|
33
|
undef $bind_var; |
|
389
|
28
|
|
|
|
|
64
|
undef $bind_field; |
|
390
|
28
|
|
|
|
|
60
|
$_ = ''; |
|
391
|
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
############################ |
|
393
|
|
|
|
|
|
|
# Blank and comment only lines |
|
394
|
|
|
|
|
|
|
} elsif (m/^(\s*|\s*#.*)$/) { |
|
395
|
4
|
|
|
|
|
22
|
my $trailing_comment = $1; |
|
396
|
4
|
50
|
|
|
|
14
|
$trailing_comment = defined ($trailing_comment) ? $trailing_comment : ''; |
|
397
|
4
|
|
|
|
|
15
|
$trailing_comment =~ s/[\r\n]+$//s; |
|
398
|
|
|
|
|
|
|
|
|
399
|
4
|
|
|
|
|
12
|
my $bind_entry = { spec => '', trailing_comment => $trailing_comment}; |
|
400
|
4
|
|
|
|
|
8
|
push (@$bind_entries, $bind_entry); |
|
401
|
4
|
|
|
|
|
8
|
$_ = ''; |
|
402
|
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
} else { |
|
404
|
0
|
|
|
|
|
0
|
die("Failed to parse BindParms block line $Acme::Sub::Parms::line_counter: $_"); |
|
405
|
|
|
|
|
|
|
} |
|
406
|
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
} else { # Start of a bind block |
|
408
|
396
|
100
|
|
|
|
741
|
if (m/^\s*BindParms\s+:\s+\((\s*#.*$|\s*$)/) { |
|
409
|
4
|
|
|
|
|
12
|
$self->{'simple_bind'} = 1; |
|
410
|
4
|
|
|
|
|
10
|
$self->{'bind_entries'} = []; |
|
411
|
4
|
|
|
|
|
8
|
$self->{'bind_block'} = 1; |
|
412
|
4
|
|
|
|
|
15
|
$self->{'line_block_start'} = $Acme::Sub::Parms::line_counter; |
|
413
|
4
|
|
|
|
|
23
|
my $block_head_comment = $2; |
|
414
|
4
|
50
|
|
|
|
26
|
$block_head_comment = defined ($block_head_comment) ? $block_head_comment : ''; |
|
415
|
4
|
|
|
|
|
8
|
$block_head_comment =~ s/[\r\n]+$//s; |
|
416
|
4
|
|
|
|
|
9
|
$_ = $block_head_comment; |
|
417
|
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
####### |
|
419
|
|
|
|
|
|
|
# ################################ |
|
420
|
|
|
|
|
|
|
# # Invokation : $self; |
|
421
|
|
|
|
|
|
|
# } elsif (my ($ihead,$ivar,$itail) = m/^(\s*)Invokation\s+:\s+(\S+.*?)\s*;(.*)$/) { |
|
422
|
|
|
|
|
|
|
# $_ = $ihead . " my $ivar = shift @_;$itail\n"; |
|
423
|
|
|
|
|
|
|
# |
|
424
|
|
|
|
|
|
|
# ################################ |
|
425
|
|
|
|
|
|
|
# # ParmsHash : %args; |
|
426
|
|
|
|
|
|
|
# } elsif (my ($fhead,$func_hash_ident,$ftail) = m/^(\s*)ParmsHash\s+:\s+(\S+.*?)\s*;(.*)$/) { |
|
427
|
|
|
|
|
|
|
# if ($normalize) { |
|
428
|
|
|
|
|
|
|
# $_ = "${fhead}my $func_hash_ident; { local \%Acme::Sub::Parms::raw_args = \@\_; $func_hash_ident = map \{ lc(\$\_\) \=\> \$Acme::Sub::Parms::raw_args\{\$\_\} \} keys \%Acme::Sub::Parms::raw_args; } $ftail\n"; |
|
429
|
|
|
|
|
|
|
# } else { |
|
430
|
|
|
|
|
|
|
# $_ = "${fhead}my $func_hash_ident = \@\_;$ftail\n"; |
|
431
|
|
|
|
|
|
|
# } |
|
432
|
|
|
|
|
|
|
# |
|
433
|
|
|
|
|
|
|
# ################################ |
|
434
|
|
|
|
|
|
|
# # MethodParms : $self, %args; |
|
435
|
|
|
|
|
|
|
# } elsif (my ($mhead,$method_invokation,$method_hash_ident,$mtail) = m/^(\s*)MethodParms\s+:\s+(\S+.*?)\s*,\s*(\S+.*?)\s*;(.*)$/) { |
|
436
|
|
|
|
|
|
|
# if ($normalize) { |
|
437
|
|
|
|
|
|
|
# $_ = "${mhead}my $method_invokation = shift; my $method_hash_ident; { local \$_; local \%Acme::Sub::Parms::raw_args = \@\_; $method_hash_ident = map \{ lc(\$\_\) \=\> \$Acme::Sub::Parms::raw_args\{\$\_\} \} keys \%Acme::Sub::Parms::raw_args; } $mtail\n"; |
|
438
|
|
|
|
|
|
|
# } else { |
|
439
|
|
|
|
|
|
|
# $_ = "${mhead}my $method_invokation = shift; my $method_hash_ident = \@\_; $mtail\n"; |
|
440
|
|
|
|
|
|
|
# } |
|
441
|
|
|
|
|
|
|
####### |
|
442
|
|
|
|
|
|
|
} |
|
443
|
|
|
|
|
|
|
} |
|
444
|
|
|
|
|
|
|
} |
|
445
|
436
|
|
|
|
|
413
|
if (_DEBUG) { |
|
446
|
|
|
|
|
|
|
print STDERR "output as: $_"; |
|
447
|
|
|
|
|
|
|
} |
|
448
|
436
|
100
|
|
|
|
562
|
if ($dump_to_stdout) { print $_; } |
|
|
110
|
|
|
|
|
154
|
|
|
449
|
|
|
|
|
|
|
|
|
450
|
436
|
|
|
|
|
11578
|
return $status; |
|
451
|
|
|
|
|
|
|
} |
|
452
|
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
#### |
|
454
|
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
1; |
|
456
|
|
|
|
|
|
|
|