| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
# -*- cperl -*- |
|
2
|
|
|
|
|
|
|
package Carp::Proxy; |
|
3
|
43
|
|
|
44
|
|
4427741
|
use warnings; |
|
|
43
|
|
|
|
|
88
|
|
|
|
43
|
|
|
|
|
1389
|
|
|
4
|
43
|
|
|
43
|
|
193
|
use strict; |
|
|
43
|
|
|
|
|
59
|
|
|
|
43
|
|
|
|
|
1151
|
|
|
5
|
43
|
|
|
43
|
|
823
|
use 5.010; |
|
|
43
|
|
|
|
|
109
|
|
|
|
43
|
|
|
|
|
1874
|
|
|
6
|
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
our $VERSION = '0.15'; |
|
8
|
|
|
|
|
|
|
|
|
9
|
43
|
|
|
43
|
|
18437
|
use Moose; |
|
|
43
|
|
|
|
|
12735954
|
|
|
|
43
|
|
|
|
|
304
|
|
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
has( 'arg', |
|
12
|
|
|
|
|
|
|
documentation => q(Perl's $ARG (AKA $_) at proxy invocation), |
|
13
|
|
|
|
|
|
|
is => 'ro', |
|
14
|
|
|
|
|
|
|
isa => 'Any', |
|
15
|
|
|
|
|
|
|
required => 1, |
|
16
|
|
|
|
|
|
|
); |
|
17
|
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
has( 'as_yaml', |
|
19
|
|
|
|
|
|
|
documentation => q(Render message as YAML dump of Carp::Proxy object), |
|
20
|
|
|
|
|
|
|
is => 'rw', |
|
21
|
|
|
|
|
|
|
isa => 'Bool', |
|
22
|
|
|
|
|
|
|
lazy => 1, |
|
23
|
|
|
|
|
|
|
builder => '_build_as_yaml', |
|
24
|
|
|
|
|
|
|
); |
|
25
|
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
has( 'banner_title', |
|
27
|
|
|
|
|
|
|
documentation => q(The first word(s) in the banner (at top of message)), |
|
28
|
|
|
|
|
|
|
is => 'rw', |
|
29
|
|
|
|
|
|
|
isa => 'Str', |
|
30
|
|
|
|
|
|
|
lazy => 1, |
|
31
|
|
|
|
|
|
|
builder => '_build_banner_title', |
|
32
|
|
|
|
|
|
|
); |
|
33
|
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
has( 'begin_hook', |
|
35
|
|
|
|
|
|
|
documentation => q(Callback before handler is launched), |
|
36
|
|
|
|
|
|
|
is => 'rw', |
|
37
|
|
|
|
|
|
|
isa => 'Maybe[CodeRef]', |
|
38
|
|
|
|
|
|
|
lazy => 1, |
|
39
|
|
|
|
|
|
|
builder => '_build_begin_hook', |
|
40
|
|
|
|
|
|
|
); |
|
41
|
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
has( 'body_indent', |
|
43
|
|
|
|
|
|
|
documentation => q(paragraph indent (beyond <header_indent>)), |
|
44
|
|
|
|
|
|
|
is => 'rw', |
|
45
|
|
|
|
|
|
|
isa => 'Int', |
|
46
|
|
|
|
|
|
|
builder => '_build_body_indent', |
|
47
|
|
|
|
|
|
|
trigger => \&_validate_body_indent, |
|
48
|
|
|
|
|
|
|
); |
|
49
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
has( 'child_error', |
|
51
|
|
|
|
|
|
|
documentation => q(Perl's $CHILD_ERROR (AKA $?) at proxy invocation), |
|
52
|
|
|
|
|
|
|
is => 'ro', |
|
53
|
|
|
|
|
|
|
isa => 'Any', |
|
54
|
|
|
|
|
|
|
required => 1, |
|
55
|
|
|
|
|
|
|
); |
|
56
|
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
has( 'columns', |
|
58
|
|
|
|
|
|
|
documentation => q( Controls width of banner and filled() paragraphs ), |
|
59
|
|
|
|
|
|
|
is => 'rw', |
|
60
|
|
|
|
|
|
|
isa => 'Int', |
|
61
|
|
|
|
|
|
|
lazy => 1, |
|
62
|
|
|
|
|
|
|
builder => '_build_columns', |
|
63
|
|
|
|
|
|
|
trigger => \&_validate_columns, |
|
64
|
|
|
|
|
|
|
); |
|
65
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
has( 'context', |
|
67
|
|
|
|
|
|
|
documentation => q( Stacktrace verbosity/inclusion in message ), |
|
68
|
|
|
|
|
|
|
is => 'rw', |
|
69
|
|
|
|
|
|
|
isa => 'Defined', |
|
70
|
|
|
|
|
|
|
lazy => 1, |
|
71
|
|
|
|
|
|
|
builder => '_build_context', |
|
72
|
|
|
|
|
|
|
trigger => \&_validate_context, |
|
73
|
|
|
|
|
|
|
); |
|
74
|
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
has( 'disposition', |
|
76
|
|
|
|
|
|
|
documentation => q( Throwing semantics ), |
|
77
|
|
|
|
|
|
|
is => 'rw', |
|
78
|
|
|
|
|
|
|
isa => 'Defined', |
|
79
|
|
|
|
|
|
|
lazy => 1, |
|
80
|
|
|
|
|
|
|
builder => '_build_disposition', |
|
81
|
|
|
|
|
|
|
trigger => \&_validate_disposition, |
|
82
|
|
|
|
|
|
|
); |
|
83
|
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
has( 'end_hook', |
|
85
|
|
|
|
|
|
|
documentation => q( Callback just before disposition ), |
|
86
|
|
|
|
|
|
|
is => 'rw', |
|
87
|
|
|
|
|
|
|
isa => 'Maybe[CodeRef]', |
|
88
|
|
|
|
|
|
|
lazy => 1, |
|
89
|
|
|
|
|
|
|
builder => '_build_end_hook', |
|
90
|
|
|
|
|
|
|
); |
|
91
|
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
has( 'eval_error', |
|
93
|
|
|
|
|
|
|
documentation => q(Perl's $EVAL_ERROR (AKA $@) at proxy invocation), |
|
94
|
|
|
|
|
|
|
is => 'ro', |
|
95
|
|
|
|
|
|
|
isa => 'Any', |
|
96
|
|
|
|
|
|
|
required => 1, |
|
97
|
|
|
|
|
|
|
); |
|
98
|
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
has( 'exit_code', |
|
100
|
|
|
|
|
|
|
documentation => q(exit-code harvested by OS when this process dies), |
|
101
|
|
|
|
|
|
|
is => 'rw', |
|
102
|
|
|
|
|
|
|
isa => 'Int', |
|
103
|
|
|
|
|
|
|
lazy => 1, |
|
104
|
|
|
|
|
|
|
builder => '_build_exit_code', |
|
105
|
|
|
|
|
|
|
); |
|
106
|
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
has( 'fq_proxy_name', |
|
108
|
|
|
|
|
|
|
documentation => q( Fully-Qualified Proxy-Name (with pkg:: prefix)), |
|
109
|
|
|
|
|
|
|
is => 'rw', |
|
110
|
|
|
|
|
|
|
isa => 'Str', |
|
111
|
|
|
|
|
|
|
required => 1, |
|
112
|
|
|
|
|
|
|
); |
|
113
|
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
has( 'handler_name', |
|
115
|
|
|
|
|
|
|
documentation => q(The name of the handler requested by the user), |
|
116
|
|
|
|
|
|
|
is => 'ro', |
|
117
|
|
|
|
|
|
|
isa => 'Str', |
|
118
|
|
|
|
|
|
|
required => 1, |
|
119
|
|
|
|
|
|
|
); |
|
120
|
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
has( 'handler_pkgs', |
|
122
|
|
|
|
|
|
|
documentation => q(Search for handler subroutines in these pkgs), |
|
123
|
|
|
|
|
|
|
is => 'rw', |
|
124
|
|
|
|
|
|
|
isa => 'ArrayRef', |
|
125
|
|
|
|
|
|
|
lazy => 1, |
|
126
|
|
|
|
|
|
|
builder => '_build_handler_pkgs', |
|
127
|
|
|
|
|
|
|
traits => ['Array'], |
|
128
|
|
|
|
|
|
|
handles => |
|
129
|
|
|
|
|
|
|
{ |
|
130
|
|
|
|
|
|
|
append_handler_package => 'push', |
|
131
|
|
|
|
|
|
|
prepend_handler_package => 'unshift', |
|
132
|
|
|
|
|
|
|
list_handler_pkgs => 'elements', |
|
133
|
|
|
|
|
|
|
}, |
|
134
|
|
|
|
|
|
|
); |
|
135
|
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
has( 'handler_prefix', |
|
137
|
|
|
|
|
|
|
documentation => q( Prefix applied to <handler_name> before lookup ), |
|
138
|
|
|
|
|
|
|
is => 'rw', |
|
139
|
|
|
|
|
|
|
isa => 'Maybe[Str]', |
|
140
|
|
|
|
|
|
|
lazy => 1, |
|
141
|
|
|
|
|
|
|
builder => '_build_handler_prefix', |
|
142
|
|
|
|
|
|
|
); |
|
143
|
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
has( 'header_indent', |
|
145
|
|
|
|
|
|
|
documentation => q( Indent from left margin for paragraph headers ), |
|
146
|
|
|
|
|
|
|
is => 'rw', |
|
147
|
|
|
|
|
|
|
isa => 'Int', |
|
148
|
|
|
|
|
|
|
lazy => 1, |
|
149
|
|
|
|
|
|
|
builder => '_build_header_indent', |
|
150
|
|
|
|
|
|
|
trigger => \&_validate_header_indent, |
|
151
|
|
|
|
|
|
|
); |
|
152
|
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
has( 'maintainer', |
|
154
|
|
|
|
|
|
|
documentation => q( Responsible party's email, phone ), |
|
155
|
|
|
|
|
|
|
is => 'rw', |
|
156
|
|
|
|
|
|
|
isa => 'Str', |
|
157
|
|
|
|
|
|
|
lazy => 1, |
|
158
|
|
|
|
|
|
|
builder => '_build_maintainer', |
|
159
|
|
|
|
|
|
|
); |
|
160
|
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
has( 'numeric_errno', |
|
162
|
|
|
|
|
|
|
documentation => q(Perl's $ERRNO (AKA $!) at proxy invocation (0+$!)), |
|
163
|
|
|
|
|
|
|
is => 'ro', |
|
164
|
|
|
|
|
|
|
isa => 'Maybe[Num]', |
|
165
|
|
|
|
|
|
|
required => 1, |
|
166
|
|
|
|
|
|
|
); |
|
167
|
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
has( 'pod_filename', |
|
169
|
|
|
|
|
|
|
documentation => q(The search for synopsis() POD is in this file), |
|
170
|
|
|
|
|
|
|
is => 'rw', |
|
171
|
|
|
|
|
|
|
isa => 'Str', |
|
172
|
|
|
|
|
|
|
lazy => 1, |
|
173
|
|
|
|
|
|
|
builder => '_build_pod_filename', |
|
174
|
|
|
|
|
|
|
); |
|
175
|
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
has( 'proxy_filename', |
|
177
|
|
|
|
|
|
|
documentation => q(The filename of the function requesting the proxy ), |
|
178
|
|
|
|
|
|
|
is => 'ro', |
|
179
|
|
|
|
|
|
|
isa => 'Str', |
|
180
|
|
|
|
|
|
|
required => 1, |
|
181
|
|
|
|
|
|
|
); |
|
182
|
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
has( 'proxy_name', |
|
184
|
|
|
|
|
|
|
documentation => q(The subname of the generated proxy function), |
|
185
|
|
|
|
|
|
|
is => 'ro', |
|
186
|
|
|
|
|
|
|
isa => 'Str', |
|
187
|
|
|
|
|
|
|
required => 1, |
|
188
|
|
|
|
|
|
|
); |
|
189
|
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
has( 'proxy_package', |
|
191
|
|
|
|
|
|
|
documentation => q(The userland package that requested the proxy), |
|
192
|
|
|
|
|
|
|
is => 'ro', |
|
193
|
|
|
|
|
|
|
isa => 'Str', |
|
194
|
|
|
|
|
|
|
required => 1, |
|
195
|
|
|
|
|
|
|
); |
|
196
|
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
has( 'section_title', |
|
198
|
|
|
|
|
|
|
documentation => q( Default title for section header ), |
|
199
|
|
|
|
|
|
|
is => 'rw', |
|
200
|
|
|
|
|
|
|
isa => 'Str', |
|
201
|
|
|
|
|
|
|
lazy => 1, |
|
202
|
|
|
|
|
|
|
builder => '_build_section_title', |
|
203
|
|
|
|
|
|
|
); |
|
204
|
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
has( 'sections', |
|
206
|
|
|
|
|
|
|
documentation => q( List of filled/fixed/raw section requests ), |
|
207
|
|
|
|
|
|
|
is => 'rw', |
|
208
|
|
|
|
|
|
|
isa => 'ArrayRef[ArrayRef]', |
|
209
|
|
|
|
|
|
|
traits => ['Array'], |
|
210
|
|
|
|
|
|
|
handles => |
|
211
|
|
|
|
|
|
|
{ |
|
212
|
|
|
|
|
|
|
append_section => 'push', |
|
213
|
|
|
|
|
|
|
prepend_section => 'unshift', |
|
214
|
|
|
|
|
|
|
list_sections => 'elements', |
|
215
|
|
|
|
|
|
|
}, |
|
216
|
|
|
|
|
|
|
builder => '_build_sections', |
|
217
|
|
|
|
|
|
|
); |
|
218
|
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
has( 'string_errno', |
|
220
|
|
|
|
|
|
|
documentation => q(Perl's $ERRNO (AKA $!) at proxy invocation (''.$!)), |
|
221
|
|
|
|
|
|
|
is => 'ro', |
|
222
|
|
|
|
|
|
|
isa => 'Maybe[Str]', |
|
223
|
|
|
|
|
|
|
required => 1, |
|
224
|
|
|
|
|
|
|
); |
|
225
|
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
has( 'tags', |
|
227
|
|
|
|
|
|
|
documentation => q( Tag-Value store for exception-related user-data ), |
|
228
|
|
|
|
|
|
|
is => 'rw', |
|
229
|
|
|
|
|
|
|
isa => 'HashRef', |
|
230
|
|
|
|
|
|
|
lazy => 1, |
|
231
|
|
|
|
|
|
|
builder => '_build_tags', |
|
232
|
|
|
|
|
|
|
); |
|
233
|
|
|
|
|
|
|
|
|
234
|
43
|
|
|
43
|
|
261225
|
no Moose; |
|
|
43
|
|
|
|
|
89
|
|
|
|
43
|
|
|
|
|
229
|
|
|
235
|
|
|
|
|
|
|
__PACKAGE__->meta->make_immutable; |
|
236
|
|
|
|
|
|
|
|
|
237
|
43
|
|
|
43
|
|
6968
|
use Config; |
|
|
43
|
|
|
|
|
64
|
|
|
|
43
|
|
|
|
|
1719
|
|
|
238
|
43
|
|
|
43
|
|
193
|
use Cwd qw( abs_path ); |
|
|
43
|
|
|
|
|
58
|
|
|
|
43
|
|
|
|
|
2464
|
|
|
239
|
43
|
|
|
43
|
|
196
|
use English qw( -no_match_vars ); |
|
|
43
|
|
|
|
|
56
|
|
|
|
43
|
|
|
|
|
310
|
|
|
240
|
43
|
|
|
43
|
|
15547
|
use Sub::Name qw( subname ); |
|
|
43
|
|
|
|
|
74
|
|
|
|
43
|
|
|
|
|
2367
|
|
|
241
|
43
|
|
|
43
|
|
596
|
use overload '""' => \&_overload_stringification; |
|
|
43
|
|
|
|
|
51
|
|
|
|
43
|
|
|
|
|
391
|
|
|
242
|
43
|
|
|
43
|
|
32938
|
use Pod::Usage qw( pod2usage ); |
|
|
43
|
|
|
|
|
1607901
|
|
|
|
43
|
|
|
|
|
4443
|
|
|
243
|
43
|
|
|
43
|
|
25296
|
use Readonly; |
|
|
43
|
|
|
|
|
102229
|
|
|
|
43
|
|
|
|
|
2567
|
|
|
244
|
43
|
|
|
43
|
|
18716
|
use YAML::XS qw( Dump ); |
|
|
43
|
|
|
|
|
90766
|
|
|
|
43
|
|
|
|
|
2448
|
|
|
245
|
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
#----- |
|
247
|
|
|
|
|
|
|
# We use an internal proxy to throw our own errors. It cannot be defined |
|
248
|
|
|
|
|
|
|
# until later, but this lets us use bareword invocation. |
|
249
|
|
|
|
|
|
|
#----- |
|
250
|
43
|
|
|
43
|
|
22317
|
use subs qw( error ); |
|
|
43
|
|
|
|
|
819
|
|
|
|
43
|
|
|
|
|
196
|
|
|
251
|
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
Readonly::Scalar my $NEWLINE => ($OSNAME =~ / win /xi) ? "\r\n" : "\n"; |
|
253
|
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
my @VALID_CONTEXT_STRINGS = qw( none die croak confess internals ); |
|
255
|
|
|
|
|
|
|
my $VALID_CONTEXT_REX = _fixed_string_rex( @VALID_CONTEXT_STRINGS ); |
|
256
|
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
my @VALID_DISPOSITION_STRINGS = qw( return warn die ); |
|
258
|
|
|
|
|
|
|
my $VALID_DISPOSITION_REX = _fixed_string_rex( @VALID_DISPOSITION_STRINGS ); |
|
259
|
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
#----- Some symbolic constants for indexing the list returned by caller() |
|
261
|
|
|
|
|
|
|
my $CALLER_PACKAGE; |
|
262
|
|
|
|
|
|
|
my $CALLER_FILENAME; |
|
263
|
|
|
|
|
|
|
my $CALLER_LINE; |
|
264
|
|
|
|
|
|
|
my $CALLER_SUBROUTINE; |
|
265
|
|
|
|
|
|
|
BEGIN { |
|
266
|
43
|
|
|
43
|
|
7092
|
Readonly::Scalar $CALLER_PACKAGE => 0; |
|
267
|
43
|
|
|
|
|
1096
|
Readonly::Scalar $CALLER_FILENAME => 1; |
|
268
|
43
|
|
|
|
|
572
|
Readonly::Scalar $CALLER_LINE => 2; |
|
269
|
43
|
|
|
|
|
531
|
Readonly::Scalar $CALLER_SUBROUTINE => 3; |
|
270
|
|
|
|
|
|
|
} |
|
271
|
|
|
|
|
|
|
|
|
272
|
424
|
|
|
424
|
|
34121
|
sub _overload_stringification { return $_[0]->render_message; } |
|
273
|
|
|
|
|
|
|
|
|
274
|
419
|
|
|
419
|
|
10599
|
sub _build_as_yaml { return 0; } |
|
275
|
375
|
|
|
375
|
|
9533
|
sub _build_banner_title { return 'Fatal'; } |
|
276
|
519
|
|
|
519
|
|
12602
|
sub _build_begin_hook { return undef; } |
|
277
|
570
|
|
|
570
|
|
16416
|
sub _build_body_indent { return 2; } |
|
278
|
442
|
|
|
442
|
|
11193
|
sub _build_columns { return 78; } |
|
279
|
378
|
|
|
378
|
|
9684
|
sub _build_context { return 'confess'; } |
|
280
|
422
|
|
|
422
|
|
10398
|
sub _build_disposition { return 'die'; } |
|
281
|
449
|
|
|
449
|
|
11095
|
sub _build_end_hook { return undef; } |
|
282
|
422
|
|
|
422
|
|
10275
|
sub _build_exit_code { return 1; } |
|
283
|
522
|
|
|
522
|
|
18734
|
sub _build_handler_pkgs { return []; } |
|
284
|
504
|
|
|
504
|
|
12582
|
sub _build_handler_prefix { return undef; } |
|
285
|
447
|
|
|
447
|
|
11549
|
sub _build_header_indent { return 2; } |
|
286
|
29
|
|
|
29
|
|
673
|
sub _build_maintainer { return ''; } |
|
287
|
28
|
|
|
28
|
|
675
|
sub _build_pod_filename { return $_[0]->proxy_filename; } |
|
288
|
18
|
|
|
18
|
|
64
|
sub _build_proxy_name { return 'fatal'; } |
|
289
|
129
|
|
|
129
|
|
2926
|
sub _build_section_title { return 'Description'; } |
|
290
|
541
|
|
|
541
|
|
16885
|
sub _build_sections { return []; } |
|
291
|
1
|
|
|
1
|
|
21
|
sub _build_tags { return {}; } |
|
292
|
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
sub _validate_body_indent { |
|
294
|
7
|
|
|
7
|
|
14
|
my( $self, $indent ) = @_; |
|
295
|
|
|
|
|
|
|
|
|
296
|
7
|
100
|
|
|
|
17
|
error 'negative_body_indentation', $indent |
|
297
|
|
|
|
|
|
|
if $indent < 0; |
|
298
|
|
|
|
|
|
|
|
|
299
|
5
|
|
|
|
|
107
|
return; |
|
300
|
|
|
|
|
|
|
} |
|
301
|
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
sub _cp_negative_body_indentation { |
|
303
|
2
|
|
|
2
|
|
5
|
my( $cp, $indent ) = @_; |
|
304
|
|
|
|
|
|
|
|
|
305
|
2
|
|
|
|
|
6
|
$cp->_disallowed_setting( 'body_indent', $indent ); |
|
306
|
|
|
|
|
|
|
|
|
307
|
2
|
|
|
|
|
4
|
return; |
|
308
|
|
|
|
|
|
|
} |
|
309
|
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
sub _validate_columns { |
|
311
|
17
|
|
|
17
|
|
28
|
my( $self, $columns ) = @_; |
|
312
|
|
|
|
|
|
|
|
|
313
|
17
|
100
|
|
|
|
44
|
error 'insufficient_columns', $columns |
|
314
|
|
|
|
|
|
|
if $columns <= 0; |
|
315
|
|
|
|
|
|
|
|
|
316
|
13
|
|
|
|
|
336
|
return; |
|
317
|
|
|
|
|
|
|
} |
|
318
|
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
sub _cp_insufficient_columns { |
|
320
|
4
|
|
|
4
|
|
6
|
my( $cp, $columns ) = @_; |
|
321
|
|
|
|
|
|
|
|
|
322
|
4
|
|
|
|
|
12
|
$cp->_disallowed_setting( 'columns', $columns ); |
|
323
|
|
|
|
|
|
|
|
|
324
|
4
|
|
|
|
|
8
|
return; |
|
325
|
|
|
|
|
|
|
} |
|
326
|
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
sub _validate_context { |
|
328
|
85
|
|
|
85
|
|
127
|
my( $self, $context ) = @_; |
|
329
|
|
|
|
|
|
|
|
|
330
|
85
|
100
|
100
|
|
|
785
|
error 'invalid_context_setting', $context |
|
331
|
|
|
|
|
|
|
if 'CODE' ne ref $context |
|
332
|
|
|
|
|
|
|
and $context !~ $VALID_CONTEXT_REX; |
|
333
|
|
|
|
|
|
|
|
|
334
|
77
|
|
|
|
|
1745
|
return; |
|
335
|
|
|
|
|
|
|
} |
|
336
|
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
sub _cp_invalid_context_setting { |
|
338
|
8
|
|
|
8
|
|
10
|
my( $cp, $context ) = @_; |
|
339
|
|
|
|
|
|
|
|
|
340
|
8
|
|
|
|
|
21
|
$cp->_disallowed_setting( 'context', $context ); |
|
341
|
|
|
|
|
|
|
|
|
342
|
8
|
|
|
|
|
17
|
return; |
|
343
|
|
|
|
|
|
|
} |
|
344
|
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
sub _validate_disposition { |
|
346
|
44
|
|
|
44
|
|
64
|
my( $self, $disposition ) = @_; |
|
347
|
|
|
|
|
|
|
|
|
348
|
44
|
100
|
100
|
|
|
348
|
error 'invalid_disposition_setting', $disposition |
|
349
|
|
|
|
|
|
|
if 'CODE' ne ref $disposition |
|
350
|
|
|
|
|
|
|
and $disposition !~ $VALID_DISPOSITION_REX; |
|
351
|
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
return |
|
353
|
38
|
|
|
|
|
1052
|
} |
|
354
|
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
sub _cp_invalid_disposition_setting { |
|
356
|
6
|
|
|
6
|
|
10
|
my( $cp, $disposition ) = @_; |
|
357
|
|
|
|
|
|
|
|
|
358
|
6
|
|
|
|
|
17
|
$cp->_disallowed_setting( 'disposition', $disposition ); |
|
359
|
|
|
|
|
|
|
|
|
360
|
6
|
|
|
|
|
15
|
return; |
|
361
|
|
|
|
|
|
|
} |
|
362
|
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
sub _validate_header_indent { |
|
364
|
7
|
|
|
7
|
|
9
|
my( $self, $indent ) = @_; |
|
365
|
|
|
|
|
|
|
|
|
366
|
7
|
100
|
|
|
|
17
|
error 'negative_header_indentation', $indent |
|
367
|
|
|
|
|
|
|
if $indent < 0; |
|
368
|
|
|
|
|
|
|
|
|
369
|
5
|
|
|
|
|
117
|
return; |
|
370
|
|
|
|
|
|
|
} |
|
371
|
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
sub _cp_negative_header_indentation { |
|
373
|
2
|
|
|
2
|
|
5
|
my( $cp, $indent ) = @_; |
|
374
|
|
|
|
|
|
|
|
|
375
|
2
|
|
|
|
|
6
|
$cp->_disallowed_setting( 'header_indent', $indent ); |
|
376
|
|
|
|
|
|
|
|
|
377
|
2
|
|
|
|
|
5
|
return; |
|
378
|
|
|
|
|
|
|
} |
|
379
|
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
BEGIN { |
|
381
|
43
|
|
|
43
|
|
29036
|
Readonly::Scalar my $POD_USAGE_SPECIFIC_SECTION => 99; |
|
382
|
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
sub _disallowed_setting { |
|
384
|
22
|
|
|
22
|
|
35
|
my( $cp, $attr, $value ) = @_; |
|
385
|
|
|
|
|
|
|
|
|
386
|
22
|
|
|
|
|
65
|
my $req = _display_code_or_string( $value ); |
|
387
|
|
|
|
|
|
|
|
|
388
|
22
|
|
|
|
|
98
|
$cp->filled(<<"EOF"); |
|
389
|
|
|
|
|
|
|
The requested setting of '$req' for the '$attr' attribute is not allowed. |
|
390
|
|
|
|
|
|
|
EOF |
|
391
|
|
|
|
|
|
|
|
|
392
|
22
|
|
|
|
|
132
|
$cp->synopsis( -verbose => $POD_USAGE_SPECIFIC_SECTION, |
|
393
|
|
|
|
|
|
|
-sections => ["ATTRIBUTES/$attr"], |
|
394
|
|
|
|
|
|
|
); |
|
395
|
22
|
|
|
|
|
82
|
return; |
|
396
|
|
|
|
|
|
|
} |
|
397
|
|
|
|
|
|
|
} |
|
398
|
|
|
|
|
|
|
|
|
399
|
|
|
|
|
|
|
sub _display_code_or_string { |
|
400
|
31
|
|
|
31
|
|
102
|
my( $value ) = @_; |
|
401
|
|
|
|
|
|
|
|
|
402
|
31
|
100
|
|
|
|
128
|
my $req |
|
|
|
100
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
= not( defined $value ) ? '(undef)' |
|
404
|
|
|
|
|
|
|
: ref( $value ) ? 'REF: ' . ref( $value ) |
|
405
|
|
|
|
|
|
|
: $value; |
|
406
|
|
|
|
|
|
|
|
|
407
|
31
|
|
|
|
|
74
|
return $req; |
|
408
|
|
|
|
|
|
|
} |
|
409
|
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
sub _fixed_string_rex { |
|
411
|
86
|
|
|
86
|
|
3309
|
my( @strings ) = @_; |
|
412
|
|
|
|
|
|
|
|
|
413
|
86
|
|
|
|
|
1275
|
my $alternations = join ' | ', @strings; |
|
414
|
|
|
|
|
|
|
|
|
415
|
86
|
|
|
|
|
4158
|
return qr{ |
|
416
|
|
|
|
|
|
|
\A |
|
417
|
|
|
|
|
|
|
(?: $alternations ) |
|
418
|
|
|
|
|
|
|
\z |
|
419
|
|
|
|
|
|
|
}x; |
|
420
|
|
|
|
|
|
|
} |
|
421
|
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
sub import { |
|
423
|
155
|
|
|
155
|
|
437695
|
my( $class, @proxy_attrlist_pairs ) = @_; |
|
424
|
|
|
|
|
|
|
|
|
425
|
155
|
|
|
|
|
241
|
my %by_proxyname; |
|
426
|
|
|
|
|
|
|
|
|
427
|
|
|
|
|
|
|
#----- |
|
428
|
|
|
|
|
|
|
# If there are no args then the user is implicitly requesting a |
|
429
|
|
|
|
|
|
|
# proxy named 'fatal'. |
|
430
|
|
|
|
|
|
|
#----- |
|
431
|
155
|
100
|
|
|
|
900
|
if (not @proxy_attrlist_pairs) { |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
432
|
|
|
|
|
|
|
|
|
433
|
19
|
|
|
|
|
136
|
$by_proxyname{ $class->_build_proxy_name() } = {}; |
|
434
|
|
|
|
|
|
|
} |
|
435
|
|
|
|
|
|
|
#----- Just one argument names a proxy with default attributes |
|
436
|
|
|
|
|
|
|
elsif ( 1 == @proxy_attrlist_pairs ) { |
|
437
|
|
|
|
|
|
|
|
|
438
|
1
|
|
|
|
|
3
|
$by_proxyname{ $proxy_attrlist_pairs[0] } = {}; |
|
439
|
|
|
|
|
|
|
} |
|
440
|
|
|
|
|
|
|
#----- Otherwise there had better be pairs... |
|
441
|
|
|
|
|
|
|
elsif ( @proxy_attrlist_pairs % 2 ) { |
|
442
|
|
|
|
|
|
|
|
|
443
|
1
|
|
|
|
|
4
|
error 'unmatched_proxy_arglist', @proxy_attrlist_pairs; |
|
444
|
|
|
|
|
|
|
} |
|
445
|
|
|
|
|
|
|
else { |
|
446
|
|
|
|
|
|
|
|
|
447
|
134
|
|
|
|
|
410
|
%by_proxyname = @proxy_attrlist_pairs; |
|
448
|
|
|
|
|
|
|
} |
|
449
|
|
|
|
|
|
|
|
|
450
|
154
|
|
|
|
|
732
|
while(my($proxy_name, $attributes) = each %by_proxyname ) { |
|
451
|
|
|
|
|
|
|
|
|
452
|
193
|
|
|
|
|
547
|
$class->_create_proxy( $proxy_name, $attributes ); |
|
453
|
|
|
|
|
|
|
} |
|
454
|
|
|
|
|
|
|
|
|
455
|
154
|
|
|
|
|
3368149
|
return; |
|
456
|
|
|
|
|
|
|
} |
|
457
|
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
sub _cp_unmatched_proxy_arglist { |
|
459
|
1
|
|
|
1
|
|
2
|
my( $cp, @mismatched_list ) = @_; |
|
460
|
|
|
|
|
|
|
|
|
461
|
1
|
|
|
|
|
1
|
my $count = @mismatched_list; |
|
462
|
|
|
|
|
|
|
|
|
463
|
1
|
|
|
|
|
1
|
my $pairings = ''; |
|
464
|
1
|
|
|
|
|
8
|
while( my( $proxy_name, $attr_val_hashref ) = |
|
465
|
|
|
|
|
|
|
splice @mismatched_list, 0, 2 |
|
466
|
|
|
|
|
|
|
) { |
|
467
|
|
|
|
|
|
|
|
|
468
|
2
|
100
|
|
|
|
4
|
$attr_val_hashref = '' |
|
469
|
|
|
|
|
|
|
if not defined $attr_val_hashref; |
|
470
|
|
|
|
|
|
|
|
|
471
|
2
|
|
|
|
|
9
|
$pairings .= "$proxy_name => $attr_val_hashref" . $NEWLINE; |
|
472
|
|
|
|
|
|
|
} |
|
473
|
|
|
|
|
|
|
|
|
474
|
1
|
|
|
|
|
5
|
$cp->filled( <<"EOF" ); |
|
475
|
|
|
|
|
|
|
Proxy creation arguments must come in (proxy, arglist) pairs. Each pair |
|
476
|
|
|
|
|
|
|
should take the form: |
|
477
|
|
|
|
|
|
|
|
|
478
|
|
|
|
|
|
|
proxy name => hashref |
|
479
|
|
|
|
|
|
|
|
|
480
|
|
|
|
|
|
|
An odd number of arguments were provided: |
|
481
|
|
|
|
|
|
|
|
|
482
|
|
|
|
|
|
|
$pairings |
|
483
|
|
|
|
|
|
|
EOF |
|
484
|
1
|
|
|
|
|
1
|
return; |
|
485
|
|
|
|
|
|
|
} |
|
486
|
|
|
|
|
|
|
|
|
487
|
|
|
|
|
|
|
sub _create_proxy { |
|
488
|
193
|
|
|
193
|
|
274
|
my( $class, $proxy_name, $requested_attributes, ) = @_; |
|
489
|
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
#----- caller(1) should be import() called from userland |
|
491
|
193
|
|
|
|
|
635
|
my ( $user_pkg, $user_fname ) = (caller 1) |
|
492
|
|
|
|
|
|
|
[ $CALLER_PACKAGE, $CALLER_FILENAME ]; |
|
493
|
|
|
|
|
|
|
|
|
494
|
193
|
|
|
|
|
4119
|
my $fq_proxy_name = $user_pkg . '::' . $proxy_name; |
|
495
|
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
#----- |
|
497
|
|
|
|
|
|
|
# The *configuration* builtin handler returns a reference to this |
|
498
|
|
|
|
|
|
|
# closure hash. |
|
499
|
|
|
|
|
|
|
#----- |
|
500
|
193
|
|
|
|
|
884
|
my %attrs = ( proxy_filename => $user_fname, |
|
501
|
|
|
|
|
|
|
proxy_name => $proxy_name, |
|
502
|
|
|
|
|
|
|
proxy_package => $user_pkg, |
|
503
|
|
|
|
|
|
|
fq_proxy_name => $fq_proxy_name, |
|
504
|
193
|
|
|
|
|
342
|
%{ $requested_attributes }, |
|
505
|
|
|
|
|
|
|
); |
|
506
|
|
|
|
|
|
|
|
|
507
|
193
|
|
|
|
|
537
|
my $proxy_coderef = _define_proxy( $class, \%attrs ); |
|
508
|
|
|
|
|
|
|
|
|
509
|
|
|
|
|
|
|
#----- |
|
510
|
|
|
|
|
|
|
# Name the coderef so that caller() reports the name instead of ANON. |
|
511
|
|
|
|
|
|
|
#----- |
|
512
|
193
|
|
|
|
|
1057
|
subname( $fq_proxy_name, $proxy_coderef ); |
|
513
|
|
|
|
|
|
|
|
|
514
|
|
|
|
|
|
|
#----- Install the proxy in userland |
|
515
|
|
|
|
|
|
|
{ |
|
516
|
43
|
|
|
43
|
|
16936
|
no strict 'refs'; |
|
|
43
|
|
|
|
|
104
|
|
|
|
43
|
|
|
|
|
81589
|
|
|
|
193
|
|
|
|
|
214
|
|
|
517
|
193
|
|
|
|
|
229
|
*{ $fq_proxy_name } = $proxy_coderef; |
|
|
193
|
|
|
|
|
831
|
|
|
518
|
|
|
|
|
|
|
} |
|
519
|
|
|
|
|
|
|
|
|
520
|
193
|
|
|
|
|
771
|
return; |
|
521
|
|
|
|
|
|
|
} |
|
522
|
|
|
|
|
|
|
|
|
523
|
|
|
|
|
|
|
sub _define_proxy { |
|
524
|
193
|
|
|
193
|
|
258
|
my( $class, $attrs ) = @_; |
|
525
|
|
|
|
|
|
|
|
|
526
|
|
|
|
|
|
|
return sub { |
|
527
|
594
|
|
|
594
|
|
4256858
|
my( $handler_name, @optional_arguments ) = @_; |
|
|
|
|
|
594
|
|
|
|
|
|
|
|
|
593
|
|
|
|
|
|
|
|
|
584
|
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
528
|
|
|
|
|
|
|
|
|
529
|
594
|
100
|
|
|
|
1742
|
return $attrs |
|
530
|
|
|
|
|
|
|
if $handler_name eq '*configuration*'; |
|
531
|
|
|
|
|
|
|
|
|
532
|
584
|
|
|
|
|
23764
|
my $cp = $class->new({ |
|
533
|
|
|
|
|
|
|
arg => $ARG, # $_ |
|
534
|
|
|
|
|
|
|
child_error => $CHILD_ERROR, # $? |
|
535
|
|
|
|
|
|
|
eval_error => $EVAL_ERROR, # $@ |
|
536
|
|
|
|
|
|
|
numeric_errno => 0 + $ERRNO, # $! |
|
537
|
|
|
|
|
|
|
string_errno => '' . $ERRNO, # $! |
|
538
|
|
|
|
|
|
|
handler_name => $handler_name, |
|
539
|
584
|
|
|
|
|
2787
|
%{ $attrs }, |
|
540
|
|
|
|
|
|
|
}); |
|
541
|
|
|
|
|
|
|
|
|
542
|
526
|
|
|
|
|
17123
|
$cp->append_handler_package( $cp->proxy_package ); |
|
543
|
|
|
|
|
|
|
|
|
544
|
526
|
|
|
|
|
13827
|
my $begin_hook = $cp->begin_hook; |
|
545
|
526
|
100
|
|
|
|
1150
|
$begin_hook->( $cp ) |
|
546
|
|
|
|
|
|
|
if defined $begin_hook; |
|
547
|
|
|
|
|
|
|
|
|
548
|
526
|
|
|
|
|
1558
|
$cp->call( $handler_name, @optional_arguments ); |
|
549
|
|
|
|
|
|
|
|
|
550
|
460
|
|
|
|
|
1233
|
$cp->add_context; |
|
551
|
|
|
|
|
|
|
|
|
552
|
455
|
|
|
|
|
12197
|
my $end_hook = $cp->end_hook; |
|
553
|
455
|
100
|
|
|
|
1039
|
$end_hook->( $cp ) |
|
554
|
|
|
|
|
|
|
if defined $end_hook; |
|
555
|
|
|
|
|
|
|
|
|
556
|
455
|
|
|
|
|
1220
|
return $cp->perform_disposition; |
|
557
|
193
|
|
|
|
|
931
|
}; |
|
558
|
|
|
|
|
|
|
} |
|
559
|
|
|
|
|
|
|
|
|
560
|
|
|
|
|
|
|
sub perform_disposition { |
|
561
|
455
|
|
|
455
|
1
|
568
|
my( $self ) = @_; |
|
562
|
|
|
|
|
|
|
|
|
563
|
455
|
|
|
|
|
11904
|
my $disposition = $self->disposition; |
|
564
|
|
|
|
|
|
|
|
|
565
|
455
|
100
|
|
|
|
2116
|
if ( not defined $disposition ) { |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
566
|
|
|
|
|
|
|
|
|
567
|
1
|
|
|
|
|
16
|
error 'unknown_disposition', $self; |
|
568
|
|
|
|
|
|
|
} |
|
569
|
|
|
|
|
|
|
elsif ( 'CODE' eq ref $disposition ) { |
|
570
|
|
|
|
|
|
|
|
|
571
|
8
|
|
|
|
|
27
|
return $disposition->( $self ); |
|
572
|
|
|
|
|
|
|
} |
|
573
|
|
|
|
|
|
|
elsif ( 'warn' eq $disposition ) { |
|
574
|
|
|
|
|
|
|
|
|
575
|
|
|
|
|
|
|
## no critic( ErrorHandling::RequireCarping ) |
|
576
|
2
|
|
|
|
|
15
|
warn $self; |
|
577
|
2
|
|
|
|
|
22
|
return (); |
|
578
|
|
|
|
|
|
|
} |
|
579
|
|
|
|
|
|
|
elsif ( 'die' eq $disposition ) { |
|
580
|
|
|
|
|
|
|
|
|
581
|
423
|
|
|
|
|
11018
|
local $ERRNO = $self->exit_code; |
|
582
|
|
|
|
|
|
|
|
|
583
|
|
|
|
|
|
|
## no critic( ErrorHandling::RequireCarping ) |
|
584
|
423
|
|
|
|
|
4782
|
die $self; |
|
585
|
|
|
|
|
|
|
} |
|
586
|
|
|
|
|
|
|
elsif ( 'return' ne $disposition ) { |
|
587
|
|
|
|
|
|
|
|
|
588
|
1
|
|
|
|
|
5
|
error 'unknown_disposition', $self; |
|
589
|
|
|
|
|
|
|
} |
|
590
|
|
|
|
|
|
|
|
|
591
|
20
|
|
|
|
|
285
|
return $self; |
|
592
|
|
|
|
|
|
|
} |
|
593
|
|
|
|
|
|
|
|
|
594
|
|
|
|
|
|
|
sub _cp_unknown_disposition { |
|
595
|
2
|
|
|
2
|
|
5
|
my( $cp, $original_cp ) = @_; |
|
596
|
|
|
|
|
|
|
|
|
597
|
2
|
|
|
|
|
88
|
my $disp = _display_code_or_string( $original_cp->disposition ); |
|
598
|
|
|
|
|
|
|
|
|
599
|
2
|
|
|
|
|
9
|
my $possibilities = join ' ', @VALID_DISPOSITION_STRINGS; |
|
600
|
|
|
|
|
|
|
|
|
601
|
2
|
|
|
|
|
7
|
_unsupported_attribute_value( $cp, |
|
602
|
|
|
|
|
|
|
$original_cp, |
|
603
|
|
|
|
|
|
|
'disposition', |
|
604
|
|
|
|
|
|
|
$disp, |
|
605
|
|
|
|
|
|
|
$possibilities ); |
|
606
|
|
|
|
|
|
|
|
|
607
|
2
|
|
|
|
|
3
|
return; |
|
608
|
|
|
|
|
|
|
} |
|
609
|
|
|
|
|
|
|
|
|
610
|
|
|
|
|
|
|
sub _unsupported_attribute_value { |
|
611
|
6
|
|
|
6
|
|
11
|
my( $cp, $original_cp, $attr, $val, $possibilities ) = @_; |
|
612
|
|
|
|
|
|
|
|
|
613
|
6
|
|
|
|
|
40
|
$cp->filled(<<"EOF"); |
|
614
|
|
|
|
|
|
|
The program has encountered an error. The developers attempted to |
|
615
|
|
|
|
|
|
|
diagnose the error but they made a mistake during the diagnosis. |
|
616
|
|
|
|
|
|
|
There are now two errors. You should complain! |
|
617
|
|
|
|
|
|
|
|
|
618
|
|
|
|
|
|
|
The secondary error is an attempt to use an unsupported value for |
|
619
|
|
|
|
|
|
|
an attribute. |
|
620
|
|
|
|
|
|
|
|
|
621
|
|
|
|
|
|
|
$attr: '$val' |
|
622
|
|
|
|
|
|
|
|
|
623
|
|
|
|
|
|
|
The supported values for $attr, beyond a CodeRef, are: |
|
624
|
|
|
|
|
|
|
|
|
625
|
|
|
|
|
|
|
$possibilities |
|
626
|
|
|
|
|
|
|
EOF |
|
627
|
|
|
|
|
|
|
|
|
628
|
6
|
|
|
|
|
20
|
$cp->_describe_primary_error( $original_cp ); |
|
629
|
6
|
|
|
|
|
8
|
return; |
|
630
|
|
|
|
|
|
|
} |
|
631
|
|
|
|
|
|
|
|
|
632
|
|
|
|
|
|
|
sub _describe_primary_error { |
|
633
|
14
|
|
|
14
|
|
20
|
my( $self, $original_cp ) = @_; |
|
634
|
|
|
|
|
|
|
|
|
635
|
14
|
|
|
|
|
36
|
$self->contact_maintainer(); |
|
636
|
|
|
|
|
|
|
|
|
637
|
14
|
|
|
|
|
38
|
$self->filled(<<'EOF', 'Primary Error' ); |
|
638
|
|
|
|
|
|
|
The remaining sections attempt to describe the original error. |
|
639
|
|
|
|
|
|
|
EOF |
|
640
|
|
|
|
|
|
|
|
|
641
|
14
|
|
|
|
|
355
|
my $st = $original_cp->section_title; |
|
642
|
14
|
|
|
|
|
464
|
foreach my $section ( $original_cp->list_sections ) { |
|
643
|
|
|
|
|
|
|
|
|
644
|
8
|
100
|
|
|
|
33
|
my $primary_title = defined( $section->[2] ) |
|
645
|
|
|
|
|
|
|
? $section->[2] |
|
646
|
|
|
|
|
|
|
: $st; |
|
647
|
|
|
|
|
|
|
|
|
648
|
|
|
|
|
|
|
#----- Turn 'Description' into 'Primary Description' etc. |
|
649
|
8
|
|
|
|
|
32
|
$primary_title =~ s/ ^ /Primary /x; |
|
650
|
|
|
|
|
|
|
|
|
651
|
8
|
|
|
|
|
361
|
$self->append_section([ $section->[0], |
|
652
|
|
|
|
|
|
|
$section->[1], |
|
653
|
|
|
|
|
|
|
$primary_title ]); |
|
654
|
|
|
|
|
|
|
} |
|
655
|
|
|
|
|
|
|
|
|
656
|
14
|
|
|
|
|
22
|
return; |
|
657
|
|
|
|
|
|
|
} |
|
658
|
|
|
|
|
|
|
|
|
659
|
|
|
|
|
|
|
sub add_context { |
|
660
|
460
|
|
|
460
|
1
|
579
|
my( $self ) = @_; |
|
661
|
|
|
|
|
|
|
|
|
662
|
460
|
|
|
|
|
13080
|
my $context = $self->context; |
|
663
|
|
|
|
|
|
|
|
|
664
|
460
|
100
|
|
|
|
2650
|
if ( not defined $context ) { error 'unknown_context', $self; } |
|
|
2
|
100
|
|
|
|
4
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
665
|
4
|
|
|
|
|
10
|
elsif ( 'CODE' eq ref $context ) { $context->($self); } |
|
666
|
4
|
|
|
|
|
12
|
elsif ( 'die' eq $context ) { $self->_die_context(); } |
|
667
|
6
|
|
|
|
|
22
|
elsif ( 'croak' eq $context ) { $self->_croak_context(); } |
|
668
|
387
|
|
|
|
|
954
|
elsif ( 'confess' eq $context ) { $self->_confess_context(); } |
|
669
|
46
|
|
|
|
|
166
|
elsif ( 'internals' eq $context ) { $self->_internals_context(); } |
|
670
|
2
|
|
|
|
|
8
|
elsif ( 'none' ne $context ) { error 'unknown_context', $self; } |
|
671
|
|
|
|
|
|
|
|
|
672
|
455
|
|
|
|
|
660
|
return; |
|
673
|
|
|
|
|
|
|
} |
|
674
|
|
|
|
|
|
|
|
|
675
|
|
|
|
|
|
|
sub _die_context { |
|
676
|
4
|
|
|
4
|
|
6
|
my( $self ) = @_; |
|
677
|
|
|
|
|
|
|
|
|
678
|
4
|
|
|
|
|
10
|
my $caller_index = $self->_find_proxy_frame(); |
|
679
|
|
|
|
|
|
|
|
|
680
|
4
|
|
|
|
|
16
|
my( $file, $line, $subr ) = $self->_file_line_subr( $caller_index ); |
|
681
|
|
|
|
|
|
|
|
|
682
|
4
|
|
|
|
|
12
|
$self->_single_frame_context( $file, $line, $subr ); |
|
683
|
|
|
|
|
|
|
|
|
684
|
4
|
|
|
|
|
6
|
return; |
|
685
|
|
|
|
|
|
|
} |
|
686
|
|
|
|
|
|
|
|
|
687
|
|
|
|
|
|
|
sub _croak_context { |
|
688
|
6
|
|
|
6
|
|
10
|
my( $self ) = @_; |
|
689
|
|
|
|
|
|
|
|
|
690
|
|
|
|
|
|
|
#----- |
|
691
|
|
|
|
|
|
|
# 'croak' semantics asks us to go back one additional frame from |
|
692
|
|
|
|
|
|
|
# where the proxy was called. |
|
693
|
|
|
|
|
|
|
#----- |
|
694
|
6
|
|
|
|
|
31
|
my $caller_index = 1 + $self->_find_proxy_frame(); |
|
695
|
|
|
|
|
|
|
|
|
696
|
6
|
|
|
|
|
24
|
my( $file, $line, $subr ) = $self->_file_line_subr( $caller_index ); |
|
697
|
|
|
|
|
|
|
|
|
698
|
|
|
|
|
|
|
#----- |
|
699
|
|
|
|
|
|
|
# If the proxy was invoked from top-level code then there is no |
|
700
|
|
|
|
|
|
|
# caller to report. In this case we fallback to 'die' semantics. |
|
701
|
|
|
|
|
|
|
#----- |
|
702
|
6
|
100
|
|
|
|
26
|
if (not defined $file) { |
|
703
|
|
|
|
|
|
|
|
|
704
|
1
|
|
|
|
|
28
|
--$caller_index; |
|
705
|
|
|
|
|
|
|
|
|
706
|
1
|
|
|
|
|
23
|
( $file, $line, $subr ) = $self->_file_line_subr( $caller_index ); |
|
707
|
|
|
|
|
|
|
} |
|
708
|
|
|
|
|
|
|
|
|
709
|
6
|
|
|
|
|
23
|
$self->_single_frame_context( $file, $line, $subr ); |
|
710
|
6
|
|
|
|
|
10
|
return; |
|
711
|
|
|
|
|
|
|
} |
|
712
|
|
|
|
|
|
|
|
|
713
|
|
|
|
|
|
|
sub _confess_context { |
|
714
|
387
|
|
|
387
|
|
467
|
my( $self ) = @_; |
|
715
|
|
|
|
|
|
|
|
|
716
|
387
|
|
|
|
|
934
|
my $caller_index = $self->_find_proxy_frame(); |
|
717
|
|
|
|
|
|
|
|
|
718
|
386
|
|
|
|
|
1112
|
$self->_multi_frame_context( $caller_index ); |
|
719
|
386
|
|
|
|
|
520
|
return; |
|
720
|
|
|
|
|
|
|
} |
|
721
|
|
|
|
|
|
|
|
|
722
|
|
|
|
|
|
|
sub _internals_context { |
|
723
|
46
|
|
|
46
|
|
70
|
my( $self ) = @_; |
|
724
|
|
|
|
|
|
|
|
|
725
|
46
|
|
|
|
|
131
|
$self->_multi_frame_context( undef ); |
|
726
|
46
|
|
|
|
|
58
|
return; |
|
727
|
|
|
|
|
|
|
} |
|
728
|
|
|
|
|
|
|
|
|
729
|
|
|
|
|
|
|
sub _cp_unknown_context { |
|
730
|
4
|
|
|
4
|
|
6
|
my( $cp, $original_cp ) = @_; |
|
731
|
|
|
|
|
|
|
|
|
732
|
4
|
|
|
|
|
86
|
my $context = _display_code_or_string( $original_cp->context ); |
|
733
|
|
|
|
|
|
|
|
|
734
|
4
|
|
|
|
|
12
|
my $possibilities = join ' ', @VALID_CONTEXT_STRINGS; |
|
735
|
|
|
|
|
|
|
|
|
736
|
4
|
|
|
|
|
10
|
_unsupported_attribute_value( $cp, |
|
737
|
|
|
|
|
|
|
$original_cp, |
|
738
|
|
|
|
|
|
|
'context', |
|
739
|
|
|
|
|
|
|
$context, |
|
740
|
|
|
|
|
|
|
$possibilities ); |
|
741
|
|
|
|
|
|
|
|
|
742
|
4
|
|
|
|
|
6
|
return; |
|
743
|
|
|
|
|
|
|
} |
|
744
|
|
|
|
|
|
|
|
|
745
|
|
|
|
|
|
|
sub _find_proxy_frame { |
|
746
|
402
|
|
|
402
|
|
469
|
my( $self ) = @_; |
|
747
|
|
|
|
|
|
|
|
|
748
|
402
|
|
|
|
|
11145
|
my $fqp = $self->fq_proxy_name; |
|
749
|
|
|
|
|
|
|
|
|
750
|
402
|
|
|
|
|
566
|
my $frame = 1; |
|
751
|
402
|
|
|
|
|
350
|
while (1) { |
|
752
|
|
|
|
|
|
|
|
|
753
|
1214
|
|
|
|
|
2747
|
my( $sub ) = (caller $frame)[ $CALLER_SUBROUTINE ]; |
|
754
|
|
|
|
|
|
|
|
|
755
|
1214
|
100
|
|
|
|
48423
|
error 'no_proxy_frame', $self |
|
756
|
|
|
|
|
|
|
if not defined $sub; |
|
757
|
|
|
|
|
|
|
|
|
758
|
|
|
|
|
|
|
last |
|
759
|
1213
|
100
|
|
|
|
2266
|
if $sub eq $fqp; |
|
760
|
|
|
|
|
|
|
|
|
761
|
812
|
|
|
|
|
836
|
++$frame; |
|
762
|
|
|
|
|
|
|
} |
|
763
|
|
|
|
|
|
|
|
|
764
|
401
|
|
|
|
|
704
|
return $frame |
|
765
|
|
|
|
|
|
|
} |
|
766
|
|
|
|
|
|
|
|
|
767
|
|
|
|
|
|
|
sub _cp_no_proxy_frame { |
|
768
|
1
|
|
|
1
|
|
3
|
my( $cp, $original_cp ) = @_; |
|
769
|
|
|
|
|
|
|
|
|
770
|
1
|
|
|
|
|
3
|
my $frames = ''; |
|
771
|
1
|
|
|
|
|
4
|
for( my $i=0; 1; ++$i ) { |
|
772
|
|
|
|
|
|
|
|
|
773
|
10
|
|
|
|
|
26
|
my( $subr ) = (caller $i)[ $CALLER_SUBROUTINE ]; |
|
774
|
|
|
|
|
|
|
|
|
775
|
|
|
|
|
|
|
last |
|
776
|
10
|
100
|
|
|
|
772
|
if not defined $subr; |
|
777
|
|
|
|
|
|
|
|
|
778
|
9
|
|
|
|
|
33
|
$frames .= " $i => $subr" . $NEWLINE; |
|
779
|
|
|
|
|
|
|
} |
|
780
|
|
|
|
|
|
|
|
|
781
|
1
|
|
|
|
|
36
|
my $proxy = $original_cp->fq_proxy_name; |
|
782
|
|
|
|
|
|
|
|
|
783
|
1
|
|
|
|
|
15
|
$cp->filled(<<"EOF"); |
|
784
|
|
|
|
|
|
|
The callstack does not appear to contain a frame for the proxy. This is |
|
785
|
|
|
|
|
|
|
an internal error. The proxy name that was the target of the search is: |
|
786
|
|
|
|
|
|
|
|
|
787
|
|
|
|
|
|
|
$proxy |
|
788
|
|
|
|
|
|
|
|
|
789
|
|
|
|
|
|
|
The following list contains the stackframe index and the associated subrotine |
|
790
|
|
|
|
|
|
|
name: |
|
791
|
|
|
|
|
|
|
EOF |
|
792
|
|
|
|
|
|
|
|
|
793
|
1
|
|
|
|
|
3
|
$cp->fixed( $frames, '' ); |
|
794
|
|
|
|
|
|
|
|
|
795
|
1
|
|
|
|
|
5
|
$cp->_describe_primary_error( $original_cp ); |
|
796
|
1
|
|
|
|
|
1
|
return; |
|
797
|
|
|
|
|
|
|
} |
|
798
|
|
|
|
|
|
|
|
|
799
|
|
|
|
|
|
|
sub _file_line_subr { |
|
800
|
2133
|
|
|
2133
|
|
2275
|
my( $self, $caller_index ) = @_; |
|
801
|
|
|
|
|
|
|
|
|
802
|
2133
|
|
|
|
|
1660
|
my( $file, $line, $subr ); |
|
803
|
|
|
|
|
|
|
|
|
804
|
2133
|
|
|
|
|
2141
|
eval{ |
|
805
|
2133
|
|
|
|
|
5182
|
( $file, $line, $subr ) = |
|
806
|
|
|
|
|
|
|
(caller 1 + $caller_index)[ |
|
807
|
|
|
|
|
|
|
$CALLER_FILENAME, |
|
808
|
|
|
|
|
|
|
$CALLER_LINE, |
|
809
|
|
|
|
|
|
|
$CALLER_SUBROUTINE, |
|
810
|
|
|
|
|
|
|
]; |
|
811
|
|
|
|
|
|
|
}; |
|
812
|
|
|
|
|
|
|
|
|
813
|
2133
|
50
|
|
|
|
150985
|
return $EVAL_ERROR ? () : ($file, $line, $subr); |
|
814
|
|
|
|
|
|
|
} |
|
815
|
|
|
|
|
|
|
|
|
816
|
|
|
|
|
|
|
sub _single_frame_context { |
|
817
|
10
|
|
|
10
|
|
14
|
my( $self, $file, $line, $subr ) = @_; |
|
818
|
|
|
|
|
|
|
|
|
819
|
10
|
|
|
|
|
33
|
my $whence = $self->_make_frame_report( $file, $line, $subr ); |
|
820
|
|
|
|
|
|
|
|
|
821
|
10
|
|
|
|
|
44
|
$self->fixed( $whence, 'Exception' ); |
|
822
|
|
|
|
|
|
|
|
|
823
|
10
|
|
|
|
|
14
|
return; |
|
824
|
|
|
|
|
|
|
} |
|
825
|
|
|
|
|
|
|
|
|
826
|
|
|
|
|
|
|
sub _section_indent { |
|
827
|
2573
|
|
|
2573
|
|
2924
|
my( $self ) = @_; |
|
828
|
|
|
|
|
|
|
|
|
829
|
2573
|
|
|
|
|
62277
|
return $self->body_indent + $self->header_indent; |
|
830
|
|
|
|
|
|
|
} |
|
831
|
|
|
|
|
|
|
|
|
832
|
|
|
|
|
|
|
sub _make_frame_report { |
|
833
|
1700
|
|
|
1700
|
|
2377
|
my( $self, $file, $line, $subr ) = @_; |
|
834
|
|
|
|
|
|
|
|
|
835
|
|
|
|
|
|
|
#----- We want to report just the basename of the subroutine (no pkg) |
|
836
|
1700
|
|
|
|
|
7154
|
$subr =~ s/\A .+ :: //x; |
|
837
|
|
|
|
|
|
|
|
|
838
|
|
|
|
|
|
|
#----- |
|
839
|
|
|
|
|
|
|
# If the filename is short enough then it will appear on the same line |
|
840
|
|
|
|
|
|
|
# as the subr and the line number. If the filename is too long then |
|
841
|
|
|
|
|
|
|
# we put the filename on the next line and indent by an extra amount. |
|
842
|
|
|
|
|
|
|
# The extra amount is an additional body_indent, or 2 spaces if there |
|
843
|
|
|
|
|
|
|
# is no body indent. |
|
844
|
|
|
|
|
|
|
#----- |
|
845
|
1700
|
|
100
|
|
|
47794
|
my $file_indent = $self->body_indent || 2; |
|
846
|
|
|
|
|
|
|
|
|
847
|
1700
|
|
|
|
|
2951
|
my $section_indent = $self->_section_indent; |
|
848
|
|
|
|
|
|
|
|
|
849
|
1700
|
|
|
|
|
3403
|
my $whence = "$subr called from line $line of"; |
|
850
|
|
|
|
|
|
|
|
|
851
|
|
|
|
|
|
|
#----- |
|
852
|
|
|
|
|
|
|
# If we were to add the filename to whence then it would need to be |
|
853
|
|
|
|
|
|
|
# separated by a space (+ 1). Also we need to account for the fact |
|
854
|
|
|
|
|
|
|
# that the report will form the body of a fixed() section, so there |
|
855
|
|
|
|
|
|
|
# will be a section indent in front of whence. |
|
856
|
|
|
|
|
|
|
#----- |
|
857
|
1700
|
|
|
|
|
2716
|
my $length_with_file = |
|
858
|
|
|
|
|
|
|
$section_indent + length( $whence ) + 1 + length( $file ); |
|
859
|
|
|
|
|
|
|
|
|
860
|
1700
|
100
|
|
|
|
41618
|
$whence .= ($self->columns >= $length_with_file ) |
|
861
|
|
|
|
|
|
|
? ' ' |
|
862
|
|
|
|
|
|
|
: $NEWLINE . (' ' x $file_indent); |
|
863
|
|
|
|
|
|
|
|
|
864
|
1700
|
|
|
|
|
2688
|
$whence .= $file . $NEWLINE; |
|
865
|
|
|
|
|
|
|
|
|
866
|
1700
|
|
|
|
|
4337
|
return $whence; |
|
867
|
|
|
|
|
|
|
} |
|
868
|
|
|
|
|
|
|
|
|
869
|
|
|
|
|
|
|
sub _multi_frame_context { |
|
870
|
432
|
|
|
432
|
|
596
|
my( $self, $starting_frame ) = @_; |
|
871
|
|
|
|
|
|
|
|
|
872
|
|
|
|
|
|
|
#----- |
|
873
|
|
|
|
|
|
|
# We have to add an extra frame to account for ourselves, unless |
|
874
|
|
|
|
|
|
|
# they want 'internals', in which case they want everything. |
|
875
|
|
|
|
|
|
|
#----- |
|
876
|
432
|
100
|
|
|
|
1157
|
$starting_frame = defined( $starting_frame ) |
|
877
|
|
|
|
|
|
|
? 1 + $starting_frame |
|
878
|
|
|
|
|
|
|
: 0; |
|
879
|
|
|
|
|
|
|
|
|
880
|
432
|
|
|
|
|
598
|
my $stacktrace = ''; |
|
881
|
432
|
|
|
|
|
589
|
for( my $frame = $starting_frame; 1; ++$frame ) { |
|
882
|
|
|
|
|
|
|
|
|
883
|
2122
|
|
|
|
|
4061
|
my( $file, $line, $subr ) = $self->_file_line_subr( $frame ); |
|
884
|
|
|
|
|
|
|
|
|
885
|
|
|
|
|
|
|
last |
|
886
|
2122
|
100
|
|
|
|
4358
|
if not defined $file; |
|
887
|
|
|
|
|
|
|
|
|
888
|
1690
|
|
|
|
|
3145
|
$stacktrace .= $self->_make_frame_report( $file, $line, $subr ); |
|
889
|
|
|
|
|
|
|
} |
|
890
|
|
|
|
|
|
|
|
|
891
|
432
|
|
|
|
|
1209
|
$self->fixed( $stacktrace, 'Stacktrace' ); |
|
892
|
|
|
|
|
|
|
|
|
893
|
432
|
|
|
|
|
521
|
return; |
|
894
|
|
|
|
|
|
|
} |
|
895
|
|
|
|
|
|
|
|
|
896
|
|
|
|
|
|
|
|
|
897
|
|
|
|
|
|
|
sub filled { |
|
898
|
416
|
|
|
416
|
1
|
941
|
my( $self, $content, $title ) = @_; |
|
899
|
|
|
|
|
|
|
|
|
900
|
416
|
|
|
|
|
16326
|
$self->append_section([ 'filled_section', $content, $title ]); |
|
901
|
416
|
|
|
|
|
588
|
return; |
|
902
|
|
|
|
|
|
|
} |
|
903
|
|
|
|
|
|
|
|
|
904
|
|
|
|
|
|
|
sub fixed { |
|
905
|
501
|
|
|
501
|
1
|
846
|
my( $self, $content, $title ) = @_; |
|
906
|
|
|
|
|
|
|
|
|
907
|
501
|
|
|
|
|
20086
|
$self->append_section([ 'fixed_section', $content, $title ]); |
|
908
|
501
|
|
|
|
|
664
|
return; |
|
909
|
|
|
|
|
|
|
} |
|
910
|
|
|
|
|
|
|
|
|
911
|
|
|
|
|
|
|
sub raw { |
|
912
|
1
|
|
|
1
|
1
|
8
|
my( $self, $content ) = @_; |
|
913
|
|
|
|
|
|
|
|
|
914
|
1
|
|
|
|
|
33
|
$self->append_section([ 'raw_section', $content ]); |
|
915
|
1
|
|
|
|
|
2
|
return; |
|
916
|
|
|
|
|
|
|
} |
|
917
|
|
|
|
|
|
|
|
|
918
|
|
|
|
|
|
|
sub filled_section { |
|
919
|
406
|
|
|
406
|
1
|
559
|
my( $self, $content, $title ) = @_; |
|
920
|
|
|
|
|
|
|
|
|
921
|
406
|
100
|
|
|
|
1408
|
return '' |
|
922
|
|
|
|
|
|
|
if $content =~ /\A \s* \z/x; |
|
923
|
|
|
|
|
|
|
|
|
924
|
405
|
|
|
|
|
951
|
my $buffer = $self->header( $title ); |
|
925
|
405
|
|
|
|
|
10452
|
my $columns = $self->columns; |
|
926
|
|
|
|
|
|
|
|
|
927
|
405
|
|
|
|
|
1958
|
my @paragraphs = split / (?: \r? \n){2,} /x, $content; |
|
928
|
|
|
|
|
|
|
|
|
929
|
405
|
|
|
|
|
885
|
my $section_indent = ' ' x $self->_section_indent; |
|
930
|
|
|
|
|
|
|
|
|
931
|
405
|
|
|
|
|
769
|
foreach my $p (@paragraphs) { |
|
932
|
|
|
|
|
|
|
|
|
933
|
|
|
|
|
|
|
#----- You need words to make a paragraph |
|
934
|
|
|
|
|
|
|
next |
|
935
|
443
|
100
|
|
|
|
1370
|
if $p =~ /\A \s* \z/x; |
|
936
|
|
|
|
|
|
|
|
|
937
|
442
|
|
|
|
|
911
|
$buffer .= _fill_paragraph( $section_indent, $columns, $p ); |
|
938
|
|
|
|
|
|
|
} |
|
939
|
|
|
|
|
|
|
|
|
940
|
405
|
|
|
|
|
1376
|
return $buffer; |
|
941
|
|
|
|
|
|
|
} |
|
942
|
|
|
|
|
|
|
|
|
943
|
|
|
|
|
|
|
sub _fill_paragraph { |
|
944
|
442
|
|
|
442
|
|
600
|
my( $indent, $columns, $text ) = @_; |
|
945
|
|
|
|
|
|
|
|
|
946
|
|
|
|
|
|
|
#----- Whitespace, where carriage-returns and newlines don't count. |
|
947
|
442
|
|
|
|
|
1530
|
my( $leading_ws ) = $text =~ /\A ( [^\r\n\S]* ) /x; |
|
948
|
|
|
|
|
|
|
|
|
949
|
|
|
|
|
|
|
#----- Any non-tab whitespace (vertical tabs, formfeeds etc) become spaces |
|
950
|
442
|
|
|
|
|
806
|
$leading_ws =~ tr/\t/ /c; |
|
951
|
442
|
|
|
|
|
955
|
$leading_ws = $indent . _expand_tabs( $leading_ws ); |
|
952
|
|
|
|
|
|
|
|
|
953
|
442
|
|
|
|
|
2429
|
my @words = split ' ', $text; |
|
954
|
442
|
|
|
|
|
941
|
my $line = $leading_ws . shift @words; |
|
955
|
442
|
|
|
|
|
548
|
my $buffer = ''; |
|
956
|
|
|
|
|
|
|
|
|
957
|
442
|
|
|
|
|
691
|
foreach my $w (@words) { |
|
958
|
|
|
|
|
|
|
|
|
959
|
4000
|
100
|
|
|
|
5199
|
if (( length( $line ) + 1 + length( $w )) <= $columns) { |
|
960
|
|
|
|
|
|
|
|
|
961
|
3855
|
|
|
|
|
4240
|
$line .= ' ' . $w; |
|
962
|
|
|
|
|
|
|
} |
|
963
|
|
|
|
|
|
|
else { |
|
964
|
|
|
|
|
|
|
|
|
965
|
145
|
|
|
|
|
260
|
$buffer .= $line . $NEWLINE; |
|
966
|
|
|
|
|
|
|
|
|
967
|
|
|
|
|
|
|
#----- Always eat one word, even if it exceeds columns |
|
968
|
145
|
|
|
|
|
254
|
$line = $leading_ws . $w; |
|
969
|
|
|
|
|
|
|
} |
|
970
|
|
|
|
|
|
|
} |
|
971
|
|
|
|
|
|
|
|
|
972
|
442
|
|
|
|
|
1030
|
$buffer .= $line . $NEWLINE . $NEWLINE; |
|
973
|
442
|
|
|
|
|
1411
|
return $buffer; |
|
974
|
|
|
|
|
|
|
} |
|
975
|
|
|
|
|
|
|
|
|
976
|
|
|
|
|
|
|
BEGIN{ |
|
977
|
43
|
|
|
43
|
|
224
|
Readonly::Scalar my $TAB => 8; |
|
978
|
|
|
|
|
|
|
|
|
979
|
|
|
|
|
|
|
sub _expand_tabs { |
|
980
|
2735
|
|
|
2735
|
|
2382
|
my( $text ) = @_; |
|
981
|
|
|
|
|
|
|
|
|
982
|
|
|
|
|
|
|
#----- Keep replacing the first tab as long as there are tabs |
|
983
|
2735
|
|
|
|
|
4840
|
1 while $text =~ s{ \A ( [^\t]* ) \t } |
|
984
|
10
|
|
|
|
|
49
|
{ $1 . (' ' x ($TAB - (length($1) % $TAB))) }xe; |
|
985
|
|
|
|
|
|
|
|
|
986
|
2735
|
|
|
|
|
5032
|
return $text; |
|
987
|
|
|
|
|
|
|
} |
|
988
|
|
|
|
|
|
|
} |
|
989
|
|
|
|
|
|
|
|
|
990
|
|
|
|
|
|
|
sub fixed_section { |
|
991
|
468
|
|
|
468
|
1
|
654
|
my( $self, $content, $title ) = @_; |
|
992
|
|
|
|
|
|
|
|
|
993
|
468
|
|
|
|
|
891
|
my $buffer = $self->header( $title ); |
|
994
|
468
|
|
|
|
|
1059
|
my $indent = ' ' x $self->_section_indent; |
|
995
|
|
|
|
|
|
|
|
|
996
|
468
|
|
|
|
|
3870
|
my @lines = split / \r? \n /x, $content; |
|
997
|
468
|
|
|
|
|
862
|
foreach my $l (@lines) { |
|
998
|
|
|
|
|
|
|
|
|
999
|
2293
|
|
|
|
|
2764
|
$buffer |
|
1000
|
|
|
|
|
|
|
.= $indent |
|
1001
|
|
|
|
|
|
|
. _expand_tabs( $l ) |
|
1002
|
|
|
|
|
|
|
. $NEWLINE; |
|
1003
|
|
|
|
|
|
|
} |
|
1004
|
|
|
|
|
|
|
|
|
1005
|
468
|
|
|
|
|
4023
|
$buffer =~ s/ \s+ \z//x; |
|
1006
|
468
|
|
|
|
|
937
|
$buffer .= $NEWLINE . $NEWLINE; |
|
1007
|
|
|
|
|
|
|
|
|
1008
|
468
|
|
|
|
|
1915
|
return $buffer; |
|
1009
|
|
|
|
|
|
|
} |
|
1010
|
|
|
|
|
|
|
|
|
1011
|
|
|
|
|
|
|
sub raw_section { |
|
1012
|
1
|
|
|
1
|
1
|
4
|
my( $self, $content ) = @_; |
|
1013
|
|
|
|
|
|
|
|
|
1014
|
1
|
|
|
|
|
3
|
return $content; |
|
1015
|
|
|
|
|
|
|
} |
|
1016
|
|
|
|
|
|
|
|
|
1017
|
|
|
|
|
|
|
sub _cp_missing_identifier { |
|
1018
|
2
|
|
|
2
|
|
4
|
my( $cp ) = @_; |
|
1019
|
|
|
|
|
|
|
|
|
1020
|
2
|
|
|
|
|
4
|
$cp->filled(<<'EOF'); |
|
1021
|
|
|
|
|
|
|
The 'name' argument for identifier_presentation() is empty or undef. |
|
1022
|
|
|
|
|
|
|
EOF |
|
1023
|
2
|
|
|
|
|
2
|
return; |
|
1024
|
|
|
|
|
|
|
} |
|
1025
|
|
|
|
|
|
|
|
|
1026
|
|
|
|
|
|
|
sub identifier_presentation { |
|
1027
|
420
|
|
|
420
|
1
|
905
|
my( $class, $name ) = @_; |
|
1028
|
|
|
|
|
|
|
|
|
1029
|
420
|
100
|
66
|
|
|
1717
|
error 'missing_identifier' |
|
1030
|
|
|
|
|
|
|
if not( defined $name ) |
|
1031
|
|
|
|
|
|
|
or not( length $name ); |
|
1032
|
|
|
|
|
|
|
|
|
1033
|
418
|
|
|
|
|
826
|
$name =~ s/ _ / /xg; |
|
1034
|
418
|
|
|
|
|
1203
|
$name =~ s{ ([[:lower:]]) ([[:upper:]]) }{ "$1 $2" }xge; |
|
|
3
|
|
|
|
|
10
|
|
|
1035
|
418
|
|
|
|
|
743
|
$name = lc $name; |
|
1036
|
|
|
|
|
|
|
|
|
1037
|
418
|
|
|
|
|
1205
|
return $name; |
|
1038
|
|
|
|
|
|
|
} |
|
1039
|
|
|
|
|
|
|
|
|
1040
|
|
|
|
|
|
|
sub header { |
|
1041
|
871
|
|
|
871
|
1
|
913
|
my( $self, $title ) = @_; |
|
1042
|
|
|
|
|
|
|
|
|
1043
|
871
|
100
|
|
|
|
1368
|
if ( defined $title ) { |
|
1044
|
|
|
|
|
|
|
|
|
1045
|
757
|
100
|
|
|
|
1614
|
return '' |
|
1046
|
|
|
|
|
|
|
if not length $title; |
|
1047
|
|
|
|
|
|
|
} |
|
1048
|
|
|
|
|
|
|
else { |
|
1049
|
|
|
|
|
|
|
|
|
1050
|
114
|
|
|
|
|
3012
|
$title = $self->section_title; |
|
1051
|
|
|
|
|
|
|
} |
|
1052
|
|
|
|
|
|
|
|
|
1053
|
861
|
|
|
|
|
23935
|
my $header |
|
1054
|
|
|
|
|
|
|
= (' ' x $self->header_indent) |
|
1055
|
|
|
|
|
|
|
. "*** ${title} ***$NEWLINE"; |
|
1056
|
|
|
|
|
|
|
|
|
1057
|
861
|
|
|
|
|
1485
|
return $header; |
|
1058
|
|
|
|
|
|
|
} |
|
1059
|
|
|
|
|
|
|
|
|
1060
|
|
|
|
|
|
|
sub banner { |
|
1061
|
419
|
|
|
419
|
1
|
522
|
my( $self ) = @_; |
|
1062
|
|
|
|
|
|
|
|
|
1063
|
419
|
|
|
|
|
10812
|
my $standout = ('~' x $self->columns) . $NEWLINE; |
|
1064
|
|
|
|
|
|
|
|
|
1065
|
419
|
|
|
|
|
10958
|
my $banner |
|
1066
|
|
|
|
|
|
|
= $standout |
|
1067
|
|
|
|
|
|
|
. $self->banner_title |
|
1068
|
|
|
|
|
|
|
. ' << ' |
|
1069
|
|
|
|
|
|
|
. $self->identifier_presentation( $self->handler_name ) |
|
1070
|
|
|
|
|
|
|
. ' >>' |
|
1071
|
|
|
|
|
|
|
. $NEWLINE |
|
1072
|
|
|
|
|
|
|
. $standout; |
|
1073
|
|
|
|
|
|
|
|
|
1074
|
419
|
|
|
|
|
755
|
return $banner; |
|
1075
|
|
|
|
|
|
|
} |
|
1076
|
|
|
|
|
|
|
|
|
1077
|
|
|
|
|
|
|
sub synopsis { |
|
1078
|
31
|
|
|
31
|
1
|
110
|
my( $self, @tag_value_pairs ) = @_; |
|
1079
|
|
|
|
|
|
|
|
|
1080
|
31
|
100
|
|
|
|
111
|
error 'odd_synopsis_augmentation', @tag_value_pairs |
|
1081
|
|
|
|
|
|
|
if @tag_value_pairs % 2; |
|
1082
|
|
|
|
|
|
|
|
|
1083
|
30
|
|
|
|
|
52
|
my $buffer = ''; |
|
1084
|
30
|
|
|
|
|
89
|
my $fd = _open_string_as_file( \$buffer ); |
|
1085
|
|
|
|
|
|
|
|
|
1086
|
30
|
|
|
|
|
46
|
eval { |
|
1087
|
30
|
|
|
|
|
868
|
pod2usage( -input => $self->pod_filename, |
|
1088
|
|
|
|
|
|
|
-output => $fd, |
|
1089
|
|
|
|
|
|
|
-exitval => 'NOEXIT', |
|
1090
|
|
|
|
|
|
|
-verbose => 0, |
|
1091
|
|
|
|
|
|
|
@tag_value_pairs ); |
|
1092
|
|
|
|
|
|
|
}; |
|
1093
|
|
|
|
|
|
|
|
|
1094
|
30
|
100
|
|
|
|
5005748
|
if ($EVAL_ERROR) { |
|
1095
|
|
|
|
|
|
|
|
|
1096
|
1
|
|
|
|
|
1
|
my $ignore = print {$fd} <<"EOF"; |
|
|
1
|
|
|
|
|
2
|
|
|
1097
|
1
|
|
|
|
|
24
|
Unable to create synopsis section from file '@{[ $self->pod_filename ]}': |
|
1098
|
|
|
|
|
|
|
|
|
1099
|
|
|
|
|
|
|
$EVAL_ERROR |
|
1100
|
|
|
|
|
|
|
EOF |
|
1101
|
|
|
|
|
|
|
} |
|
1102
|
|
|
|
|
|
|
|
|
1103
|
30
|
|
|
|
|
135
|
_close_string_file( $fd ); |
|
1104
|
|
|
|
|
|
|
|
|
1105
|
30
|
|
|
|
|
116
|
$self->fixed( $buffer, 'Synopsis' ); |
|
1106
|
30
|
|
|
|
|
146
|
return; |
|
1107
|
|
|
|
|
|
|
} |
|
1108
|
|
|
|
|
|
|
|
|
1109
|
|
|
|
|
|
|
sub _open_string_as_file { |
|
1110
|
30
|
|
|
30
|
|
36
|
my( $string_ref ) = @_; |
|
1111
|
|
|
|
|
|
|
|
|
1112
|
30
|
50
|
|
187
|
|
795
|
open my( $fd ), '>', $string_ref |
|
|
4
|
|
|
|
|
26
|
|
|
|
4
|
|
|
|
|
8
|
|
|
|
4
|
|
|
|
|
29
|
|
|
1113
|
|
|
|
|
|
|
or error 'cannot_open_string'; |
|
1114
|
|
|
|
|
|
|
|
|
1115
|
30
|
|
|
|
|
4055
|
return $fd; |
|
1116
|
|
|
|
|
|
|
} |
|
1117
|
|
|
|
|
|
|
|
|
1118
|
|
|
|
|
|
|
sub _cp_cannot_open_string { |
|
1119
|
1
|
|
|
1
|
|
1
|
my( $cp ) = @_; |
|
1120
|
|
|
|
|
|
|
|
|
1121
|
1
|
|
|
|
|
3
|
$cp->filled( <<"EOF" ); |
|
1122
|
|
|
|
|
|
|
Unable to create a file descriptor using a string as the storage medium. |
|
1123
|
|
|
|
|
|
|
EOF |
|
1124
|
1
|
|
|
|
|
3
|
$cp->errno_section; |
|
1125
|
1
|
|
|
|
|
1
|
return; |
|
1126
|
|
|
|
|
|
|
} |
|
1127
|
|
|
|
|
|
|
|
|
1128
|
|
|
|
|
|
|
sub _close_string_file { |
|
1129
|
30
|
|
|
30
|
|
59
|
my( $fd ) = @_; |
|
1130
|
|
|
|
|
|
|
|
|
1131
|
30
|
50
|
|
|
|
150
|
close $fd |
|
1132
|
|
|
|
|
|
|
or error 'cannot_close_string'; |
|
1133
|
|
|
|
|
|
|
|
|
1134
|
30
|
|
|
|
|
98
|
return; |
|
1135
|
|
|
|
|
|
|
} |
|
1136
|
|
|
|
|
|
|
|
|
1137
|
|
|
|
|
|
|
sub _cp_cannot_close_string { |
|
1138
|
1
|
|
|
1
|
|
2
|
my( $cp ) = @_; |
|
1139
|
|
|
|
|
|
|
|
|
1140
|
1
|
|
|
|
|
3
|
$cp->filled( <<"EOF" ); |
|
1141
|
|
|
|
|
|
|
Unable to close a file-descriptor that points to a string buffer as the |
|
1142
|
|
|
|
|
|
|
storage medium. |
|
1143
|
|
|
|
|
|
|
EOF |
|
1144
|
1
|
|
|
|
|
3
|
$cp->errno_section; |
|
1145
|
1
|
|
|
|
|
1
|
return; |
|
1146
|
|
|
|
|
|
|
} |
|
1147
|
|
|
|
|
|
|
|
|
1148
|
|
|
|
|
|
|
sub _cp_odd_synopsis_augmentation { |
|
1149
|
1
|
|
|
1
|
|
3
|
my( $cp, @tag_value_pairs ) = @_; |
|
1150
|
|
|
|
|
|
|
|
|
1151
|
1
|
|
|
|
|
2
|
my $tv_report = ''; |
|
1152
|
1
|
|
|
|
|
19
|
while( @tag_value_pairs >= 2 ) { |
|
1153
|
|
|
|
|
|
|
|
|
1154
|
2
|
|
|
|
|
5
|
my( $t, $v ) = splice @tag_value_pairs, 0, 2; |
|
1155
|
|
|
|
|
|
|
|
|
1156
|
2
|
|
|
|
|
7
|
$tv_report .= "$t => $v" . $NEWLINE; |
|
1157
|
|
|
|
|
|
|
} |
|
1158
|
|
|
|
|
|
|
|
|
1159
|
1
|
|
|
|
|
2
|
$tv_report .= "$tag_value_pairs[0] =>" . $NEWLINE; |
|
1160
|
|
|
|
|
|
|
|
|
1161
|
1
|
|
|
|
|
5
|
$cp->filled( <<"EOF" ); |
|
1162
|
|
|
|
|
|
|
The synopsis() method allows users to supplement pod2usage() arguments |
|
1163
|
|
|
|
|
|
|
with tag-value pairs. The supplied arguments did not come in pairs; there |
|
1164
|
|
|
|
|
|
|
are an odd number. |
|
1165
|
|
|
|
|
|
|
|
|
1166
|
|
|
|
|
|
|
$tv_report |
|
1167
|
|
|
|
|
|
|
EOF |
|
1168
|
1
|
|
|
|
|
2
|
return; |
|
1169
|
|
|
|
|
|
|
} |
|
1170
|
|
|
|
|
|
|
|
|
1171
|
|
|
|
|
|
|
sub usage { |
|
1172
|
5
|
|
|
5
|
1
|
16
|
my( $self ) = @_; |
|
1173
|
|
|
|
|
|
|
|
|
1174
|
5
|
|
|
|
|
11
|
for(my $index = $self->_find_proxy_frame(); 1; ++$index ) { |
|
1175
|
|
|
|
|
|
|
|
|
1176
|
13
|
|
|
|
|
21
|
my( $subr ) = (caller $index)[ $CALLER_SUBROUTINE ]; |
|
1177
|
|
|
|
|
|
|
|
|
1178
|
13
|
100
|
|
|
|
764
|
error 'no_usage_documentation', $self |
|
1179
|
|
|
|
|
|
|
if not defined $subr; |
|
1180
|
|
|
|
|
|
|
|
|
1181
|
|
|
|
|
|
|
#----- Discard any package qualifiers |
|
1182
|
12
|
|
|
|
|
45
|
$subr =~ s/ \A .* :: //x; |
|
1183
|
|
|
|
|
|
|
|
|
1184
|
12
|
|
|
|
|
15
|
my $handler = 'usage_' . $subr; |
|
1185
|
|
|
|
|
|
|
|
|
1186
|
12
|
|
|
|
|
21
|
my $where = $self->_locate_handler( $handler ); |
|
1187
|
|
|
|
|
|
|
|
|
1188
|
|
|
|
|
|
|
next |
|
1189
|
12
|
100
|
|
|
|
21
|
if not $where; |
|
1190
|
|
|
|
|
|
|
|
|
1191
|
4
|
|
|
|
|
10
|
$where->( $self ); |
|
1192
|
4
|
|
|
|
|
8
|
last; |
|
1193
|
|
|
|
|
|
|
} |
|
1194
|
|
|
|
|
|
|
|
|
1195
|
4
|
|
|
|
|
4
|
return; |
|
1196
|
|
|
|
|
|
|
} |
|
1197
|
|
|
|
|
|
|
|
|
1198
|
|
|
|
|
|
|
sub _cp_no_usage_documentation { |
|
1199
|
1
|
|
|
1
|
|
2
|
my( $cp, $original_cp ) = @_; |
|
1200
|
|
|
|
|
|
|
|
|
1201
|
1
|
|
|
|
|
4
|
$cp->filled(<<"EOF"); |
|
1202
|
|
|
|
|
|
|
There was an error. The developers caught the error and attempted to |
|
1203
|
|
|
|
|
|
|
describe it. Part of the description was supposed to be provided by a |
|
1204
|
|
|
|
|
|
|
"usage" subroutine. Unfortunately they forgot to define the usage |
|
1205
|
|
|
|
|
|
|
subroutine. Now there are two errors. You shoud complain! |
|
1206
|
|
|
|
|
|
|
EOF |
|
1207
|
|
|
|
|
|
|
|
|
1208
|
1
|
|
|
|
|
22
|
my $prefix = $original_cp->handler_prefix; |
|
1209
|
|
|
|
|
|
|
|
|
1210
|
1
|
|
50
|
|
|
6
|
$prefix //= '(undef)'; |
|
1211
|
|
|
|
|
|
|
|
|
1212
|
1
|
|
|
|
|
2
|
$cp->fixed(<<"EOF", 'Missing Handler - Secondary Error'); |
|
1213
|
1
|
|
|
|
|
30
|
handler_pkgs: @{[ join ' : ', $original_cp->list_handler_pkgs ]} |
|
1214
|
|
|
|
|
|
|
handler_prefix: $prefix |
|
1215
|
|
|
|
|
|
|
EOF |
|
1216
|
|
|
|
|
|
|
|
|
1217
|
1
|
|
|
|
|
4
|
$cp->_describe_primary_error( $original_cp ); |
|
1218
|
1
|
|
|
|
|
2
|
return; |
|
1219
|
|
|
|
|
|
|
} |
|
1220
|
|
|
|
|
|
|
|
|
1221
|
|
|
|
|
|
|
BEGIN{ |
|
1222
|
43
|
|
|
43
|
|
53642
|
Readonly::Scalar my $ONE_BYTE => 8; |
|
1223
|
43
|
|
|
|
|
912
|
Readonly::Scalar my $SIGNAL_MASK => 0x7F; |
|
1224
|
43
|
|
|
|
|
591
|
Readonly::Scalar my $CORE_DUMP => 0x80; |
|
1225
|
|
|
|
|
|
|
|
|
1226
|
|
|
|
|
|
|
sub decipher_child_error { |
|
1227
|
256
|
|
|
256
|
1
|
1430
|
my( $cp ) = shift; |
|
1228
|
|
|
|
|
|
|
|
|
1229
|
256
|
50
|
33
|
|
|
8093
|
my $child_error = ( @_ and defined( $_[0] ) and $_[0] =~ /\A \d+ \z/x ) |
|
1230
|
|
|
|
|
|
|
? shift |
|
1231
|
|
|
|
|
|
|
: $cp->child_error; |
|
1232
|
|
|
|
|
|
|
|
|
1233
|
256
|
100
|
|
|
|
598
|
if ( 0 == $child_error ) { |
|
1234
|
|
|
|
|
|
|
|
|
1235
|
1
|
|
|
|
|
5
|
$cp->filled( 'The child process completed normally (exit code 0).', |
|
1236
|
|
|
|
|
|
|
'Process Succeeded' ); |
|
1237
|
1
|
|
|
|
|
2
|
return; |
|
1238
|
|
|
|
|
|
|
} |
|
1239
|
|
|
|
|
|
|
|
|
1240
|
255
|
|
|
|
|
418
|
my $signal = $child_error & $SIGNAL_MASK; |
|
1241
|
255
|
100
|
|
|
|
518
|
if ($signal) { |
|
1242
|
|
|
|
|
|
|
|
|
1243
|
254
|
|
|
|
|
8436
|
my @names = split ' ', $Config{sig_name}; |
|
1244
|
254
|
|
|
|
|
9091
|
my @nums = split ' ', $Config{sig_num}; |
|
1245
|
|
|
|
|
|
|
|
|
1246
|
254
|
|
|
|
|
904
|
my %by_num; |
|
1247
|
254
|
|
|
|
|
8508
|
@by_num{ @nums } = @names; |
|
1248
|
|
|
|
|
|
|
|
|
1249
|
254
|
|
|
|
|
450
|
my $sig_name = $by_num{ $signal }; |
|
1250
|
|
|
|
|
|
|
|
|
1251
|
254
|
100
|
|
|
|
1298
|
my $msg |
|
|
|
100
|
|
|
|
|
|
|
1252
|
|
|
|
|
|
|
= 'The child process was terminated by ' |
|
1253
|
|
|
|
|
|
|
. ((defined $sig_name) |
|
1254
|
|
|
|
|
|
|
? "SIG$sig_name (signal $signal)." |
|
1255
|
|
|
|
|
|
|
: "signal $signal.") |
|
1256
|
|
|
|
|
|
|
. (($child_error & $CORE_DUMP) |
|
1257
|
|
|
|
|
|
|
? ' There was a core dump.' |
|
1258
|
|
|
|
|
|
|
: ''); |
|
1259
|
|
|
|
|
|
|
|
|
1260
|
254
|
|
|
|
|
771
|
$cp->filled( $msg, 'Process terminated by signal' ); |
|
1261
|
254
|
|
|
|
|
4878
|
return; |
|
1262
|
|
|
|
|
|
|
} |
|
1263
|
|
|
|
|
|
|
|
|
1264
|
1
|
|
|
|
|
3
|
my $exit_code = $child_error >> $ONE_BYTE; |
|
1265
|
|
|
|
|
|
|
|
|
1266
|
1
|
|
|
|
|
7
|
$cp->filled( "The child process terminated with exit code $exit_code.", |
|
1267
|
|
|
|
|
|
|
'Process returns failing status' ); |
|
1268
|
1
|
|
|
|
|
1
|
return; |
|
1269
|
|
|
|
|
|
|
} |
|
1270
|
|
|
|
|
|
|
} |
|
1271
|
|
|
|
|
|
|
|
|
1272
|
|
|
|
|
|
|
sub filename { |
|
1273
|
2
|
|
|
2
|
1
|
13
|
my( $cp, $file, $title ) = @_; |
|
1274
|
|
|
|
|
|
|
|
|
1275
|
2
|
100
|
|
|
|
6
|
$title = 'Filename' |
|
1276
|
|
|
|
|
|
|
if not defined $title; |
|
1277
|
|
|
|
|
|
|
|
|
1278
|
2
|
|
|
|
|
8
|
$cp->_abs_path_section( $file, $title ); |
|
1279
|
2
|
|
|
|
|
3
|
return; |
|
1280
|
|
|
|
|
|
|
} |
|
1281
|
|
|
|
|
|
|
|
|
1282
|
|
|
|
|
|
|
sub directory { |
|
1283
|
2
|
|
|
2
|
1
|
12
|
my( $cp, $dir, $title ) = @_; |
|
1284
|
|
|
|
|
|
|
|
|
1285
|
2
|
100
|
|
|
|
7
|
$title = 'Directory' |
|
1286
|
|
|
|
|
|
|
if not defined $title; |
|
1287
|
|
|
|
|
|
|
|
|
1288
|
2
|
|
|
|
|
6
|
$cp->_abs_path_section( $dir, $title ); |
|
1289
|
2
|
|
|
|
|
4
|
return; |
|
1290
|
|
|
|
|
|
|
} |
|
1291
|
|
|
|
|
|
|
|
|
1292
|
|
|
|
|
|
|
sub _abs_path_section { |
|
1293
|
4
|
|
|
4
|
|
7
|
my( $cp, $entry, $title ) = @_; |
|
1294
|
|
|
|
|
|
|
|
|
1295
|
4
|
|
|
|
|
4
|
my $path; |
|
1296
|
|
|
|
|
|
|
|
|
1297
|
|
|
|
|
|
|
#----- |
|
1298
|
|
|
|
|
|
|
# On *nix abs_path() appears to return undef if it has trouble. On |
|
1299
|
|
|
|
|
|
|
# Windows it appears to throw. Docs are ambiguous. |
|
1300
|
|
|
|
|
|
|
#----- |
|
1301
|
4
|
|
|
|
|
5
|
eval{ $path = abs_path( $entry ); }; |
|
|
4
|
|
|
|
|
132
|
|
|
1302
|
|
|
|
|
|
|
|
|
1303
|
4
|
100
|
66
|
|
|
21
|
$path = $entry |
|
1304
|
|
|
|
|
|
|
if not( defined $path ) |
|
1305
|
|
|
|
|
|
|
or $EVAL_ERROR; |
|
1306
|
|
|
|
|
|
|
|
|
1307
|
4
|
|
|
|
|
10
|
$cp->fixed( $path, $title ); |
|
1308
|
|
|
|
|
|
|
|
|
1309
|
4
|
|
|
|
|
3
|
return; |
|
1310
|
|
|
|
|
|
|
} |
|
1311
|
|
|
|
|
|
|
|
|
1312
|
|
|
|
|
|
|
sub errno_section { |
|
1313
|
6
|
|
|
6
|
1
|
19
|
my( $cp, $title ) = @_; |
|
1314
|
|
|
|
|
|
|
|
|
1315
|
6
|
|
|
|
|
138
|
my $string_errno = $cp->string_errno; |
|
1316
|
|
|
|
|
|
|
|
|
1317
|
|
|
|
|
|
|
return |
|
1318
|
6
|
100
|
66
|
|
|
23
|
if not( defined $string_errno ) |
|
1319
|
|
|
|
|
|
|
or not( length $string_errno ); |
|
1320
|
|
|
|
|
|
|
|
|
1321
|
2
|
100
|
|
|
|
4
|
$title = 'System Diagnostic' |
|
1322
|
|
|
|
|
|
|
if not defined $title; |
|
1323
|
|
|
|
|
|
|
|
|
1324
|
2
|
|
|
|
|
5
|
$cp->filled( $string_errno, $title ); |
|
1325
|
2
|
|
|
|
|
2
|
return; |
|
1326
|
|
|
|
|
|
|
} |
|
1327
|
|
|
|
|
|
|
|
|
1328
|
|
|
|
|
|
|
sub render_message { |
|
1329
|
424
|
|
|
424
|
1
|
613
|
my( $self ) = @_; |
|
1330
|
|
|
|
|
|
|
|
|
1331
|
424
|
100
|
|
|
|
12525
|
return Dump( $self ) |
|
1332
|
|
|
|
|
|
|
if $self->as_yaml; |
|
1333
|
|
|
|
|
|
|
|
|
1334
|
420
|
|
|
|
|
1137
|
my $buffer = $self->banner; |
|
1335
|
|
|
|
|
|
|
|
|
1336
|
420
|
|
|
|
|
15295
|
my @sections = $self->list_sections; |
|
1337
|
420
|
|
|
|
|
814
|
foreach my $s (@sections) { |
|
1338
|
|
|
|
|
|
|
|
|
1339
|
875
|
|
|
|
|
973
|
my( $meth, @args ) = @{ $s }; |
|
|
875
|
|
|
|
|
1702
|
|
|
1340
|
|
|
|
|
|
|
|
|
1341
|
875
|
|
|
|
|
2667
|
$buffer .= $self->$meth( @args ); |
|
1342
|
|
|
|
|
|
|
} |
|
1343
|
420
|
|
|
|
|
3783
|
return $buffer; |
|
1344
|
|
|
|
|
|
|
} |
|
1345
|
|
|
|
|
|
|
|
|
1346
|
|
|
|
|
|
|
sub call { |
|
1347
|
528
|
|
|
528
|
1
|
951
|
my( $self, $handler, @args ) = @_; |
|
1348
|
|
|
|
|
|
|
|
|
1349
|
528
|
|
|
|
|
1259
|
my $where = $self->_locate_handler( $handler ); |
|
1350
|
|
|
|
|
|
|
|
|
1351
|
528
|
100
|
|
|
|
1165
|
error 'embarrassed_developers', $self, $handler |
|
1352
|
|
|
|
|
|
|
if not $where; |
|
1353
|
|
|
|
|
|
|
|
|
1354
|
522
|
|
|
|
|
1609
|
$where->( $self, @args ); |
|
1355
|
|
|
|
|
|
|
|
|
1356
|
462
|
|
|
|
|
5870
|
return; |
|
1357
|
|
|
|
|
|
|
} |
|
1358
|
|
|
|
|
|
|
|
|
1359
|
|
|
|
|
|
|
sub _locate_handler { |
|
1360
|
540
|
|
|
540
|
|
630
|
my( $self, $handler_name ) = @_; |
|
1361
|
|
|
|
|
|
|
|
|
1362
|
540
|
|
|
|
|
489
|
my $coderef; |
|
1363
|
|
|
|
|
|
|
|
|
1364
|
540
|
100
|
|
|
|
1448
|
if ($handler_name =~ /\A [*] ( .+ ) [*] \z/x) { |
|
1365
|
|
|
|
|
|
|
|
|
1366
|
13
|
|
|
|
|
22
|
my $builtin = $1; |
|
1367
|
13
|
|
|
|
|
65
|
$coderef = $self->can( '_builtin_' . $builtin ); |
|
1368
|
|
|
|
|
|
|
} |
|
1369
|
|
|
|
|
|
|
else { |
|
1370
|
|
|
|
|
|
|
|
|
1371
|
527
|
|
|
|
|
14332
|
my $handler_prefix = $self->handler_prefix; |
|
1372
|
|
|
|
|
|
|
|
|
1373
|
527
|
100
|
|
|
|
2025
|
my @prefixes = (defined $handler_prefix) |
|
1374
|
|
|
|
|
|
|
? ( $handler_prefix ) |
|
1375
|
|
|
|
|
|
|
: ( '_cp_', '_', '' ); |
|
1376
|
|
|
|
|
|
|
|
|
1377
|
527
|
|
|
|
|
19273
|
PKG: foreach my $pkg ($self->list_handler_pkgs) { |
|
1378
|
|
|
|
|
|
|
|
|
1379
|
529
|
|
|
|
|
740
|
foreach my $pre (@prefixes) { |
|
1380
|
|
|
|
|
|
|
|
|
1381
|
1474
|
|
|
|
|
6528
|
$coderef = $pkg->can( $pre . $handler_name ); |
|
1382
|
|
|
|
|
|
|
|
|
1383
|
|
|
|
|
|
|
last PKG |
|
1384
|
1474
|
100
|
|
|
|
3455
|
if $coderef; |
|
1385
|
|
|
|
|
|
|
} |
|
1386
|
|
|
|
|
|
|
} |
|
1387
|
|
|
|
|
|
|
} |
|
1388
|
|
|
|
|
|
|
|
|
1389
|
540
|
|
|
|
|
1165
|
return $coderef; |
|
1390
|
|
|
|
|
|
|
} |
|
1391
|
|
|
|
|
|
|
|
|
1392
|
|
|
|
|
|
|
sub _cp_embarrassed_developers { |
|
1393
|
6
|
|
|
6
|
|
8
|
my( $cp, $original_cp, $handler ) = @_; |
|
1394
|
|
|
|
|
|
|
|
|
1395
|
6
|
|
|
|
|
11
|
$cp->filled(<<"EOF"); |
|
1396
|
|
|
|
|
|
|
There was an error. The developers caught the error and attempted to |
|
1397
|
|
|
|
|
|
|
pass diagnosis off to a handler. Unfortunately they forgot to define |
|
1398
|
|
|
|
|
|
|
the handler. Now there are two errors. You shoud complain! |
|
1399
|
|
|
|
|
|
|
EOF |
|
1400
|
|
|
|
|
|
|
|
|
1401
|
6
|
|
|
|
|
138
|
my $prefix = $original_cp->handler_prefix; |
|
1402
|
|
|
|
|
|
|
|
|
1403
|
6
|
|
100
|
|
|
11
|
$prefix //= '(undef)'; |
|
1404
|
|
|
|
|
|
|
|
|
1405
|
6
|
100
|
|
|
|
12
|
$prefix = q('') |
|
1406
|
|
|
|
|
|
|
if not length $prefix; |
|
1407
|
|
|
|
|
|
|
|
|
1408
|
6
|
|
|
|
|
11
|
$cp->fixed(<<"EOF", 'Missing Handler - Secondary Error'); |
|
1409
|
6
|
|
|
|
|
165
|
handler_name: $handler |
|
1410
|
|
|
|
|
|
|
handler_pkgs: @{[ join ' : ', $original_cp->list_handler_pkgs ]} |
|
1411
|
|
|
|
|
|
|
handler_prefix: $prefix |
|
1412
|
|
|
|
|
|
|
EOF |
|
1413
|
|
|
|
|
|
|
|
|
1414
|
6
|
|
|
|
|
15
|
$cp->_describe_primary_error( $original_cp ); |
|
1415
|
6
|
|
|
|
|
5
|
return; |
|
1416
|
|
|
|
|
|
|
} |
|
1417
|
|
|
|
|
|
|
|
|
1418
|
|
|
|
|
|
|
sub _builtin_internal_error { |
|
1419
|
8
|
|
|
8
|
|
10
|
my( $cp, @args ) = @_; |
|
1420
|
|
|
|
|
|
|
|
|
1421
|
8
|
100
|
|
|
|
25
|
$cp->filled( "@args" ) |
|
1422
|
|
|
|
|
|
|
if @args; |
|
1423
|
|
|
|
|
|
|
|
|
1424
|
8
|
|
|
|
|
22
|
$cp->contact_maintainer; |
|
1425
|
|
|
|
|
|
|
|
|
1426
|
8
|
|
|
|
|
7
|
return; |
|
1427
|
|
|
|
|
|
|
} |
|
1428
|
|
|
|
|
|
|
|
|
1429
|
|
|
|
|
|
|
sub _builtin_assertion_failure { |
|
1430
|
5
|
|
|
5
|
|
8
|
my( $cp, $description, $hashref ) = @_; |
|
1431
|
|
|
|
|
|
|
|
|
1432
|
5
|
|
|
|
|
6
|
my $boilerplate = <<"EOF"; |
|
1433
|
|
|
|
|
|
|
An assertion has failed. This indicates that the internal state of |
|
1434
|
|
|
|
|
|
|
the program is corrupt. |
|
1435
|
|
|
|
|
|
|
EOF |
|
1436
|
|
|
|
|
|
|
|
|
1437
|
5
|
100
|
100
|
|
|
25
|
$boilerplate .= $NEWLINE . $description |
|
1438
|
|
|
|
|
|
|
if defined( $description ) |
|
1439
|
|
|
|
|
|
|
and length( $description ); |
|
1440
|
|
|
|
|
|
|
|
|
1441
|
5
|
|
|
|
|
12
|
$cp->filled( $boilerplate ); |
|
1442
|
|
|
|
|
|
|
|
|
1443
|
5
|
|
|
|
|
10
|
$cp->contact_maintainer; |
|
1444
|
|
|
|
|
|
|
|
|
1445
|
5
|
100
|
100
|
|
|
17
|
if (defined( $hashref ) and keys %{ $hashref }) { |
|
|
2
|
|
|
|
|
8
|
|
|
1446
|
|
|
|
|
|
|
|
|
1447
|
1
|
|
|
|
|
88
|
my $yaml = Dump( $hashref ); |
|
1448
|
|
|
|
|
|
|
|
|
1449
|
1
|
|
|
|
|
5
|
$cp->fixed( $yaml, 'Salient State (YAML)' ); |
|
1450
|
|
|
|
|
|
|
} |
|
1451
|
|
|
|
|
|
|
|
|
1452
|
5
|
|
|
|
|
116
|
$cp->context( 'confess' ); |
|
1453
|
|
|
|
|
|
|
|
|
1454
|
5
|
|
|
|
|
7
|
return; |
|
1455
|
|
|
|
|
|
|
} |
|
1456
|
|
|
|
|
|
|
|
|
1457
|
|
|
|
|
|
|
sub contact_maintainer { |
|
1458
|
31
|
|
|
31
|
1
|
52
|
my( $cp ) = @_; |
|
1459
|
|
|
|
|
|
|
|
|
1460
|
31
|
|
|
|
|
885
|
my $maintainer = $cp->maintainer; |
|
1461
|
|
|
|
|
|
|
|
|
1462
|
31
|
100
|
|
|
|
85
|
$cp->fixed( $maintainer, 'Please contact the maintainer' ) |
|
1463
|
|
|
|
|
|
|
if length $maintainer; |
|
1464
|
|
|
|
|
|
|
|
|
1465
|
31
|
|
|
|
|
42
|
return; |
|
1466
|
|
|
|
|
|
|
} |
|
1467
|
|
|
|
|
|
|
|
|
1468
|
|
|
|
|
|
|
BEGIN { |
|
1469
|
|
|
|
|
|
|
|
|
1470
|
|
|
|
|
|
|
#----- |
|
1471
|
|
|
|
|
|
|
# The real intent of this eval is to add another frame to the |
|
1472
|
|
|
|
|
|
|
# callstack so that create_proxy() installs error() into the |
|
1473
|
|
|
|
|
|
|
# Carp::Proxy package. |
|
1474
|
|
|
|
|
|
|
#----- |
|
1475
|
43
|
|
|
43
|
|
33671
|
eval { |
|
1476
|
43
|
|
|
|
|
448
|
__PACKAGE__->import( 'error', |
|
1477
|
|
|
|
|
|
|
{ |
|
1478
|
|
|
|
|
|
|
banner_title => 'Oops', |
|
1479
|
|
|
|
|
|
|
context => 'internals', |
|
1480
|
|
|
|
|
|
|
}); |
|
1481
|
|
|
|
|
|
|
}; |
|
1482
|
|
|
|
|
|
|
|
|
1483
|
|
|
|
|
|
|
## no critic( ErrorHandling::RequireCarping ) |
|
1484
|
43
|
50
|
|
|
|
3888
|
die $EVAL_ERROR if $EVAL_ERROR; |
|
1485
|
|
|
|
|
|
|
} |
|
1486
|
|
|
|
|
|
|
|
|
1487
|
|
|
|
|
|
|
|
|
1488
|
|
|
|
|
|
|
1; |
|
1489
|
|
|
|
|
|
|
|
|
1490
|
|
|
|
|
|
|
__END__ |
|
1491
|
|
|
|
|
|
|
|
|
1492
|
|
|
|
|
|
|
=pod |
|
1493
|
|
|
|
|
|
|
|
|
1494
|
|
|
|
|
|
|
=begin stopwords |
|
1495
|
|
|
|
|
|
|
|
|
1496
|
|
|
|
|
|
|
accessor |
|
1497
|
|
|
|
|
|
|
accessors |
|
1498
|
|
|
|
|
|
|
AnnoCPAN |
|
1499
|
|
|
|
|
|
|
arg |
|
1500
|
|
|
|
|
|
|
arg-checking |
|
1501
|
|
|
|
|
|
|
ArrayRef |
|
1502
|
|
|
|
|
|
|
ArrayRefs |
|
1503
|
|
|
|
|
|
|
boolean |
|
1504
|
|
|
|
|
|
|
boundarys |
|
1505
|
|
|
|
|
|
|
builtin |
|
1506
|
|
|
|
|
|
|
BUILTIN |
|
1507
|
|
|
|
|
|
|
callstack |
|
1508
|
|
|
|
|
|
|
camelCasedIdentifiers |
|
1509
|
|
|
|
|
|
|
CodeRef |
|
1510
|
|
|
|
|
|
|
CPAN |
|
1511
|
|
|
|
|
|
|
CPAN's |
|
1512
|
|
|
|
|
|
|
customizable |
|
1513
|
|
|
|
|
|
|
dereferences |
|
1514
|
|
|
|
|
|
|
filename |
|
1515
|
|
|
|
|
|
|
HashRef |
|
1516
|
|
|
|
|
|
|
hashref |
|
1517
|
|
|
|
|
|
|
initializations |
|
1518
|
|
|
|
|
|
|
invoker |
|
1519
|
|
|
|
|
|
|
invoker-upward |
|
1520
|
|
|
|
|
|
|
Liebert |
|
1521
|
|
|
|
|
|
|
logfile |
|
1522
|
|
|
|
|
|
|
multi-line |
|
1523
|
|
|
|
|
|
|
parameterized |
|
1524
|
|
|
|
|
|
|
perldoc |
|
1525
|
|
|
|
|
|
|
perlvar |
|
1526
|
|
|
|
|
|
|
prepended |
|
1527
|
|
|
|
|
|
|
Proxys |
|
1528
|
|
|
|
|
|
|
regex |
|
1529
|
|
|
|
|
|
|
repeatability |
|
1530
|
|
|
|
|
|
|
runtime |
|
1531
|
|
|
|
|
|
|
rw |
|
1532
|
|
|
|
|
|
|
stackframe |
|
1533
|
|
|
|
|
|
|
stackframes |
|
1534
|
|
|
|
|
|
|
Stackframes |
|
1535
|
|
|
|
|
|
|
stacktrace |
|
1536
|
|
|
|
|
|
|
stacktraces |
|
1537
|
|
|
|
|
|
|
STDERR |
|
1538
|
|
|
|
|
|
|
stringification |
|
1539
|
|
|
|
|
|
|
tradeoff |
|
1540
|
|
|
|
|
|
|
undef |
|
1541
|
|
|
|
|
|
|
whitespace |
|
1542
|
|
|
|
|
|
|
YAML |
|
1543
|
|
|
|
|
|
|
|
|
1544
|
|
|
|
|
|
|
=end stopwords |
|
1545
|
|
|
|
|
|
|
|
|
1546
|
|
|
|
|
|
|
=head1 NAME |
|
1547
|
|
|
|
|
|
|
|
|
1548
|
|
|
|
|
|
|
Carp::Proxy - Diagnostic delegation |
|
1549
|
|
|
|
|
|
|
|
|
1550
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
1551
|
|
|
|
|
|
|
|
|
1552
|
|
|
|
|
|
|
use Carp::Proxy; |
|
1553
|
|
|
|
|
|
|
|
|
1554
|
|
|
|
|
|
|
fatal 'handler_subroutine', @optional_arguments |
|
1555
|
|
|
|
|
|
|
if not $assertion; |
|
1556
|
|
|
|
|
|
|
|
|
1557
|
|
|
|
|
|
|
sub handler_subroutine { |
|
1558
|
|
|
|
|
|
|
my( $proxy_object, @optional_arguments ) = @_; |
|
1559
|
|
|
|
|
|
|
|
|
1560
|
|
|
|
|
|
|
$proxy_object->filled( 'explanation' ); |
|
1561
|
|
|
|
|
|
|
return; |
|
1562
|
|
|
|
|
|
|
} |
|
1563
|
|
|
|
|
|
|
|
|
1564
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
1565
|
|
|
|
|
|
|
|
|
1566
|
|
|
|
|
|
|
B<Carp::Proxy> is a framework for throwing exceptions. The goal is to |
|
1567
|
|
|
|
|
|
|
couple the small lexical footprint of the B<die()> statement with |
|
1568
|
|
|
|
|
|
|
support for comprehensive error messages. Good diagnostics pay for |
|
1569
|
|
|
|
|
|
|
themselves; let's make them easier to produce. |
|
1570
|
|
|
|
|
|
|
|
|
1571
|
|
|
|
|
|
|
Error messages in Perl are commonly coded with idioms like: |
|
1572
|
|
|
|
|
|
|
|
|
1573
|
|
|
|
|
|
|
die 'explanation' |
|
1574
|
|
|
|
|
|
|
if not $assertion; |
|
1575
|
|
|
|
|
|
|
|
|
1576
|
|
|
|
|
|
|
The idiom is attractive when the explanation is simple. If an |
|
1577
|
|
|
|
|
|
|
explanation grows to more than a few words, or if it requires |
|
1578
|
|
|
|
|
|
|
calculation, then the surrounding flow becomes disrupted. The |
|
1579
|
|
|
|
|
|
|
solution, of course, is to offload failing assertions to a subroutine. |
|
1580
|
|
|
|
|
|
|
|
|
1581
|
|
|
|
|
|
|
Subroutines that perform diagnosis, compose error messages and throw |
|
1582
|
|
|
|
|
|
|
exceptions tend to have repeated code at the beginning and end, with |
|
1583
|
|
|
|
|
|
|
unique content somewhere in the middle. B<Carp::Proxy> proposes a |
|
1584
|
|
|
|
|
|
|
wrapper subroutine, called a Proxy, to factor out the repeated sections. |
|
1585
|
|
|
|
|
|
|
|
|
1586
|
|
|
|
|
|
|
fatal 'user_subroutine' |
|
1587
|
|
|
|
|
|
|
if not $assertion; |
|
1588
|
|
|
|
|
|
|
|
|
1589
|
|
|
|
|
|
|
Proxys, like B<fatal()>, serve as elaborate, customizable replacements |
|
1590
|
|
|
|
|
|
|
for B<warn()>, B<die()> and members of the B<Carp::> family like |
|
1591
|
|
|
|
|
|
|
B<confess()>. If we look at B<warn()>, B<die()>, B<confess()> and the |
|
1592
|
|
|
|
|
|
|
others, we notice that they are all just different variations on two themes: |
|
1593
|
|
|
|
|
|
|
|
|
1594
|
|
|
|
|
|
|
- Add locational context to a user-supplied message. |
|
1595
|
|
|
|
|
|
|
- Throw some kind of exception. |
|
1596
|
|
|
|
|
|
|
|
|
1597
|
|
|
|
|
|
|
B<Carp::Proxy> parameterizes the two themes into attributes of an |
|
1598
|
|
|
|
|
|
|
exception object that is created whenever a Proxy is called. The |
|
1599
|
|
|
|
|
|
|
Proxy passes the object to a user-defined "Handler" subroutine which |
|
1600
|
|
|
|
|
|
|
is responsible for constructing the diagnostic message. When the |
|
1601
|
|
|
|
|
|
|
Handler returns, the Proxy optionally adds "Context" (a stacktrace) to |
|
1602
|
|
|
|
|
|
|
the message and performs "Disposition", typically by calling B<die()>. |
|
1603
|
|
|
|
|
|
|
|
|
1604
|
|
|
|
|
|
|
When the object is constructed it captures the state of Perl's error |
|
1605
|
|
|
|
|
|
|
variables, for later examination by the Handler. The object provides |
|
1606
|
|
|
|
|
|
|
methods that aid in message composition. Attributes control message |
|
1607
|
|
|
|
|
|
|
formatting, stacktrace generation and how Disposition will be handled. |
|
1608
|
|
|
|
|
|
|
|
|
1609
|
|
|
|
|
|
|
The object overloads Perl's stringification operator with a message |
|
1610
|
|
|
|
|
|
|
rendering method, causing uncaught exceptions to be nicely formatted. |
|
1611
|
|
|
|
|
|
|
Exceptions that are caught can be modified and re-thrown. |
|
1612
|
|
|
|
|
|
|
|
|
1613
|
|
|
|
|
|
|
=head1 WE ARE THE 99% |
|
1614
|
|
|
|
|
|
|
|
|
1615
|
|
|
|
|
|
|
B<Carp::Proxy> has a long list of features, but getting started is easy. |
|
1616
|
|
|
|
|
|
|
All you need for most day-to-day work is the Proxy and two methods: |
|
1617
|
|
|
|
|
|
|
|
|
1618
|
|
|
|
|
|
|
fatal() The (default) Proxy. |
|
1619
|
|
|
|
|
|
|
filled() Auto-formatting message builder method. |
|
1620
|
|
|
|
|
|
|
fixed() Pre-formatted message builder method. |
|
1621
|
|
|
|
|
|
|
|
|
1622
|
|
|
|
|
|
|
Use B<fatal()> wherever you currently use B<die()>. Your Handler should |
|
1623
|
|
|
|
|
|
|
compose the diagnostic text using the L<filled()|/filled> and/or |
|
1624
|
|
|
|
|
|
|
L<fixed()|/fixed> methods. |
|
1625
|
|
|
|
|
|
|
|
|
1626
|
|
|
|
|
|
|
=head1 SAMPLE OUTPUT |
|
1627
|
|
|
|
|
|
|
|
|
1628
|
|
|
|
|
|
|
The formatted messages produced by the Proxy start off with a |
|
1629
|
|
|
|
|
|
|
"Banner". The Banner includes a title and the name of the Handler. |
|
1630
|
|
|
|
|
|
|
As the Banner is the first thing seen by users, it is helpful if the |
|
1631
|
|
|
|
|
|
|
Handler name conveys a terse description of the situation. |
|
1632
|
|
|
|
|
|
|
|
|
1633
|
|
|
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
1634
|
|
|
|
|
|
|
Fatal: << cannot overwrite >> |
|
1635
|
|
|
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
1636
|
|
|
|
|
|
|
|
|
1637
|
|
|
|
|
|
|
Following the Banner are a series of "Sections" containing paragraphs of |
|
1638
|
|
|
|
|
|
|
descriptive text. Each Section is introduced by a "Header" sub-title |
|
1639
|
|
|
|
|
|
|
that is wrapped in *** stars ***. |
|
1640
|
|
|
|
|
|
|
|
|
1641
|
|
|
|
|
|
|
*** Description *** |
|
1642
|
|
|
|
|
|
|
The destination file already exists. An attempt was made |
|
1643
|
|
|
|
|
|
|
to overwrite it, but the attempt failed. This might have |
|
1644
|
|
|
|
|
|
|
happened because of permission problems, or possibly if |
|
1645
|
|
|
|
|
|
|
the destination is not a file (i.e. a directory or link |
|
1646
|
|
|
|
|
|
|
or something else). |
|
1647
|
|
|
|
|
|
|
|
|
1648
|
|
|
|
|
|
|
Either remove the destination manually, or choose a |
|
1649
|
|
|
|
|
|
|
different destination. |
|
1650
|
|
|
|
|
|
|
|
|
1651
|
|
|
|
|
|
|
*** Destination Filename *** |
|
1652
|
|
|
|
|
|
|
/home/isaac/muse/content |
|
1653
|
|
|
|
|
|
|
|
|
1654
|
|
|
|
|
|
|
*** ls(1) output *** |
|
1655
|
|
|
|
|
|
|
-r--r--r-- 1 isaac users 21626 Aug 5 17:22 content |
|
1656
|
|
|
|
|
|
|
|
|
1657
|
|
|
|
|
|
|
*** System Diagnostic *** |
|
1658
|
|
|
|
|
|
|
Permission denied |
|
1659
|
|
|
|
|
|
|
|
|
1660
|
|
|
|
|
|
|
*** Stacktrace *** |
|
1661
|
|
|
|
|
|
|
fatal called from line 273 of /usr/bin/cantu |
|
1662
|
|
|
|
|
|
|
set_output called from line 244 of /usr/bin/cantu |
|
1663
|
|
|
|
|
|
|
main called from line 24 of /usr/bin/cantu |
|
1664
|
|
|
|
|
|
|
|
|
1665
|
|
|
|
|
|
|
Here is the corresponding Handler code. Note that most of the Handler's |
|
1666
|
|
|
|
|
|
|
body is dedicated to producing message content; there is very little |
|
1667
|
|
|
|
|
|
|
overhead. Handlers are easy to write. |
|
1668
|
|
|
|
|
|
|
|
|
1669
|
|
|
|
|
|
|
sub cannot_overwrite { |
|
1670
|
|
|
|
|
|
|
my( $cp, $filename ) = @_; |
|
1671
|
|
|
|
|
|
|
|
|
1672
|
|
|
|
|
|
|
$cp->filled(<<"EOF"); |
|
1673
|
|
|
|
|
|
|
The destination file already exists. An attempt was made to |
|
1674
|
|
|
|
|
|
|
overwrite it, but the attempt failed. This might have happened |
|
1675
|
|
|
|
|
|
|
because of permission problems, or possibly if the destination |
|
1676
|
|
|
|
|
|
|
is not a file (i.e. a directory or link or something else). |
|
1677
|
|
|
|
|
|
|
|
|
1678
|
|
|
|
|
|
|
Either remove the destination manually, or choose a different |
|
1679
|
|
|
|
|
|
|
destination. |
|
1680
|
|
|
|
|
|
|
EOF |
|
1681
|
|
|
|
|
|
|
$cp->filename( $filename, 'Destination Filename' ); |
|
1682
|
|
|
|
|
|
|
$cp->fixed( qx{ /bin/ls -ld $filename }, 'ls(1) output' ); |
|
1683
|
|
|
|
|
|
|
$cp->errno_section; |
|
1684
|
|
|
|
|
|
|
return; |
|
1685
|
|
|
|
|
|
|
} |
|
1686
|
|
|
|
|
|
|
|
|
1687
|
|
|
|
|
|
|
=head1 EXPORTS |
|
1688
|
|
|
|
|
|
|
|
|
1689
|
|
|
|
|
|
|
B<Carp::Proxy> defines an exception class. Depending on the arguments |
|
1690
|
|
|
|
|
|
|
supplied to B<use()>, B<Carp::Proxy> also generates Proxy subroutines |
|
1691
|
|
|
|
|
|
|
for export. The generation part is important: B<Carp::Proxy> |
|
1692
|
|
|
|
|
|
|
implements the B<import()> method as a function factory. |
|
1693
|
|
|
|
|
|
|
|
|
1694
|
|
|
|
|
|
|
Proxy customization is performed by supplying a HashRef of |
|
1695
|
|
|
|
|
|
|
B<attribute =E<gt> parameter> pairs for each desired Proxy. |
|
1696
|
|
|
|
|
|
|
The arguments to B<use()> or B<import()> look like this: |
|
1697
|
|
|
|
|
|
|
|
|
1698
|
|
|
|
|
|
|
proxy_name1 => |
|
1699
|
|
|
|
|
|
|
{ |
|
1700
|
|
|
|
|
|
|
attribute => parameter, |
|
1701
|
|
|
|
|
|
|
... |
|
1702
|
|
|
|
|
|
|
}, |
|
1703
|
|
|
|
|
|
|
|
|
1704
|
|
|
|
|
|
|
proxy_name2 => |
|
1705
|
|
|
|
|
|
|
{ |
|
1706
|
|
|
|
|
|
|
attribute => parameter, |
|
1707
|
|
|
|
|
|
|
... |
|
1708
|
|
|
|
|
|
|
}, |
|
1709
|
|
|
|
|
|
|
... |
|
1710
|
|
|
|
|
|
|
|
|
1711
|
|
|
|
|
|
|
If there is only one argument, i.e. a proxy-name key with no corresponding |
|
1712
|
|
|
|
|
|
|
value, then an empty HashRef, C<{}>, where all attributes assume defaults, |
|
1713
|
|
|
|
|
|
|
is implied. |
|
1714
|
|
|
|
|
|
|
|
|
1715
|
|
|
|
|
|
|
Here are some examples: |
|
1716
|
|
|
|
|
|
|
|
|
1717
|
|
|
|
|
|
|
#----- |
|
1718
|
|
|
|
|
|
|
# All three of these 'use' statements generate and export a |
|
1719
|
|
|
|
|
|
|
# Proxy named fatal() with defaults for all attributes. |
|
1720
|
|
|
|
|
|
|
#----- |
|
1721
|
|
|
|
|
|
|
use Carp::Proxy; |
|
1722
|
|
|
|
|
|
|
use Carp::Proxy 'fatal'; |
|
1723
|
|
|
|
|
|
|
use Carp::Proxy fatal => {}; |
|
1724
|
|
|
|
|
|
|
|
|
1725
|
|
|
|
|
|
|
#----- |
|
1726
|
|
|
|
|
|
|
# This statement is the same as all of the above, except |
|
1727
|
|
|
|
|
|
|
# that now the Proxy is named error() instead of fatal(). |
|
1728
|
|
|
|
|
|
|
#----- |
|
1729
|
|
|
|
|
|
|
use Carp::Proxy 'error'; |
|
1730
|
|
|
|
|
|
|
|
|
1731
|
|
|
|
|
|
|
#----- |
|
1732
|
|
|
|
|
|
|
# Here we export two proxys, oops() and warning(), each with |
|
1733
|
|
|
|
|
|
|
# different sets of attributes. |
|
1734
|
|
|
|
|
|
|
#----- |
|
1735
|
|
|
|
|
|
|
use Carp::Proxy oops => { context => 'internals' }, |
|
1736
|
|
|
|
|
|
|
warning => { banner_title => 'Warning', |
|
1737
|
|
|
|
|
|
|
disposition => 'warn' }; |
|
1738
|
|
|
|
|
|
|
|
|
1739
|
|
|
|
|
|
|
#----- No exports. Class definition only. |
|
1740
|
|
|
|
|
|
|
use Carp::Proxy (); |
|
1741
|
|
|
|
|
|
|
|
|
1742
|
|
|
|
|
|
|
The no-export form is desirable if you want the class definition for your |
|
1743
|
|
|
|
|
|
|
own purposes, or if Proxy attributes need to be established at runtime. |
|
1744
|
|
|
|
|
|
|
You can invoke L<import()|/import>, at any time, to build Proxy subroutines. |
|
1745
|
|
|
|
|
|
|
|
|
1746
|
|
|
|
|
|
|
use Carp::Proxy (); |
|
1747
|
|
|
|
|
|
|
... |
|
1748
|
|
|
|
|
|
|
Carp::Proxy->import( expire => { end_hook => $log_me }); |
|
1749
|
|
|
|
|
|
|
|
|
1750
|
|
|
|
|
|
|
=head1 PROXY INVOCATION |
|
1751
|
|
|
|
|
|
|
|
|
1752
|
|
|
|
|
|
|
Usage: |
|
1753
|
|
|
|
|
|
|
<proxy> $handler, @optional_arguments; |
|
1754
|
|
|
|
|
|
|
|
|
1755
|
|
|
|
|
|
|
The default L<proxy_name|/proxy_name> is C<fatal> so the typical |
|
1756
|
|
|
|
|
|
|
usage looks more like |
|
1757
|
|
|
|
|
|
|
|
|
1758
|
|
|
|
|
|
|
fatal $handler, @optional_arguments; |
|
1759
|
|
|
|
|
|
|
|
|
1760
|
|
|
|
|
|
|
I<$handler> is expected to be a string (NOT a CodeRef!) that names a |
|
1761
|
|
|
|
|
|
|
user-defined subroutine. |
|
1762
|
|
|
|
|
|
|
|
|
1763
|
|
|
|
|
|
|
The Proxy performs the following actions: |
|
1764
|
|
|
|
|
|
|
|
|
1765
|
|
|
|
|
|
|
=over 4 |
|
1766
|
|
|
|
|
|
|
|
|
1767
|
|
|
|
|
|
|
=item B<1 - Capture the Environment> |
|
1768
|
|
|
|
|
|
|
|
|
1769
|
|
|
|
|
|
|
Perl's error/status variables $ARG, $ERRNO, $CHILD_ERROR and $EVAL_ERROR |
|
1770
|
|
|
|
|
|
|
(also known as B<$_>, B<$!>, B<$?> and B<$@>, respectively) are all |
|
1771
|
|
|
|
|
|
|
captured as soon as possible to preserve their values for examination by |
|
1772
|
|
|
|
|
|
|
I<$handler>. |
|
1773
|
|
|
|
|
|
|
|
|
1774
|
|
|
|
|
|
|
=item B<2 - Create a Carp::Proxy object> |
|
1775
|
|
|
|
|
|
|
|
|
1776
|
|
|
|
|
|
|
The Proxy supplies settings for all the object's required attributes, |
|
1777
|
|
|
|
|
|
|
see L<ATTRIBUTES|/ATTRIBUTES>. The Proxy also |
|
1778
|
|
|
|
|
|
|
forwards initializations for any attributes supplied by the user (arguments |
|
1779
|
|
|
|
|
|
|
to B<use()> or L<import()|/import>). |
|
1780
|
|
|
|
|
|
|
|
|
1781
|
|
|
|
|
|
|
=item B<3 - Call begin_hook> |
|
1782
|
|
|
|
|
|
|
|
|
1783
|
|
|
|
|
|
|
The L<begin_hook|/begin_hook> attribute, if it exists, is |
|
1784
|
|
|
|
|
|
|
called, passing the object as the only argument. |
|
1785
|
|
|
|
|
|
|
|
|
1786
|
|
|
|
|
|
|
=item B<4 - Locate the Handler> |
|
1787
|
|
|
|
|
|
|
|
|
1788
|
|
|
|
|
|
|
Locating the Handler is a complex process; see |
|
1789
|
|
|
|
|
|
|
L<HANDLER SEARCH|/HANDLER-SEARCH:>. Briefly, the default behavior is to use |
|
1790
|
|
|
|
|
|
|
the first subroutine it finds from the following list of templates. The |
|
1791
|
|
|
|
|
|
|
list is evaluated once for each package in the |
|
1792
|
|
|
|
|
|
|
L<handler_pkgs|/handler_pkgs> attribute. |
|
1793
|
|
|
|
|
|
|
|
|
1794
|
|
|
|
|
|
|
<package>::_cp_<handler_name> |
|
1795
|
|
|
|
|
|
|
<package>::_<handler_name> |
|
1796
|
|
|
|
|
|
|
<package>::<handler_name> |
|
1797
|
|
|
|
|
|
|
|
|
1798
|
|
|
|
|
|
|
=item B<5 - Call Handler> |
|
1799
|
|
|
|
|
|
|
|
|
1800
|
|
|
|
|
|
|
The Handler is called with the object as the first argument. Any |
|
1801
|
|
|
|
|
|
|
arguments passed to the Proxy, beyond the handler-name, are propagated as |
|
1802
|
|
|
|
|
|
|
additional arguments to the Handler. |
|
1803
|
|
|
|
|
|
|
|
|
1804
|
|
|
|
|
|
|
=item B<6 - Add Calling Context (Stacktrace)> |
|
1805
|
|
|
|
|
|
|
|
|
1806
|
|
|
|
|
|
|
The method L<add_context()|/add_context> is invoked to generate a |
|
1807
|
|
|
|
|
|
|
Section with stacktrace content, as dictated by the |
|
1808
|
|
|
|
|
|
|
L<context|/context> attribute. |
|
1809
|
|
|
|
|
|
|
|
|
1810
|
|
|
|
|
|
|
=item B<7 - Call end_hook> |
|
1811
|
|
|
|
|
|
|
|
|
1812
|
|
|
|
|
|
|
The L<end_hook|/end_hook> attribute, if it exists, is called, |
|
1813
|
|
|
|
|
|
|
passing the object as the only argument. |
|
1814
|
|
|
|
|
|
|
|
|
1815
|
|
|
|
|
|
|
=item B<8 - Perform Disposition> |
|
1816
|
|
|
|
|
|
|
|
|
1817
|
|
|
|
|
|
|
The method L<perform_disposition()|/perform_disposition> is |
|
1818
|
|
|
|
|
|
|
invoked. Disposition is controlled by the |
|
1819
|
|
|
|
|
|
|
L<disposition|/disposition> attribute; typically this means |
|
1820
|
|
|
|
|
|
|
passing the B<Carp::Proxy> object to B<die()>. |
|
1821
|
|
|
|
|
|
|
|
|
1822
|
|
|
|
|
|
|
=back |
|
1823
|
|
|
|
|
|
|
|
|
1824
|
|
|
|
|
|
|
If L<perform_disposition()|/perform_disposition> returns, rather |
|
1825
|
|
|
|
|
|
|
than throwing, then the returned value is propagated as the return value |
|
1826
|
|
|
|
|
|
|
of the Proxy. |
|
1827
|
|
|
|
|
|
|
|
|
1828
|
|
|
|
|
|
|
=head1 ATTRIBUTES |
|
1829
|
|
|
|
|
|
|
|
|
1830
|
|
|
|
|
|
|
All B<Carp::Proxy> object attributes have correspondingly named accessors. |
|
1831
|
|
|
|
|
|
|
When the accessors are invoked without arguments, they return the |
|
1832
|
|
|
|
|
|
|
attribute's value. Mutable (Read-Write) attributes have accessors that can |
|
1833
|
|
|
|
|
|
|
be supplied with an argument to set the attribute's value. |
|
1834
|
|
|
|
|
|
|
|
|
1835
|
|
|
|
|
|
|
Users generally do not create B<Carp::Proxy> objects directly; the Proxy |
|
1836
|
|
|
|
|
|
|
does that for them. The object constructor, L<new()|/new>, requires |
|
1837
|
|
|
|
|
|
|
specification for several of the attributes like |
|
1838
|
|
|
|
|
|
|
L<eval_error|/eval_error>. The Proxy supplies these required |
|
1839
|
|
|
|
|
|
|
attributes, but arguments to B<use()> or L<import()|/import> can override them. |
|
1840
|
|
|
|
|
|
|
|
|
1841
|
|
|
|
|
|
|
All other attributes invoke a "builder" method to initialize the |
|
1842
|
|
|
|
|
|
|
attribute value if one is not provided. Builder |
|
1843
|
|
|
|
|
|
|
methods are named with a prefix of B<'_build_'>. You can change default |
|
1844
|
|
|
|
|
|
|
values for these attributes with arguments to B<use()> / L<import()|/import>, |
|
1845
|
|
|
|
|
|
|
or by providing custom builder functions in a sub-class. |
|
1846
|
|
|
|
|
|
|
|
|
1847
|
|
|
|
|
|
|
=head2 arg |
|
1848
|
|
|
|
|
|
|
|
|
1849
|
|
|
|
|
|
|
I<arg> holds the value of Perl's B<$ARG ($_)>, as harvested from the |
|
1850
|
|
|
|
|
|
|
invoking environment. This can be handy if you are using |
|
1851
|
|
|
|
|
|
|
B<Try::Tiny>. |
|
1852
|
|
|
|
|
|
|
|
|
1853
|
|
|
|
|
|
|
=over 4 |
|
1854
|
|
|
|
|
|
|
|
|
1855
|
|
|
|
|
|
|
=item Builder: None; L<new()|/new> requires I<arg> specification. |
|
1856
|
|
|
|
|
|
|
|
|
1857
|
|
|
|
|
|
|
=item Default: N/A |
|
1858
|
|
|
|
|
|
|
|
|
1859
|
|
|
|
|
|
|
=item Domain: Any |
|
1860
|
|
|
|
|
|
|
|
|
1861
|
|
|
|
|
|
|
=item Affects: For user convenience; not used by B<Carp::Proxy> |
|
1862
|
|
|
|
|
|
|
|
|
1863
|
|
|
|
|
|
|
=item Mutability: Read-Only |
|
1864
|
|
|
|
|
|
|
|
|
1865
|
|
|
|
|
|
|
=back |
|
1866
|
|
|
|
|
|
|
|
|
1867
|
|
|
|
|
|
|
=head2 as_yaml |
|
1868
|
|
|
|
|
|
|
|
|
1869
|
|
|
|
|
|
|
The I<as_yaml> attribute is a flag that controls message rendering. |
|
1870
|
|
|
|
|
|
|
When False, message text is derived from the |
|
1871
|
|
|
|
|
|
|
L<sections|/sections> attribute; this is the normal mode of |
|
1872
|
|
|
|
|
|
|
operation. |
|
1873
|
|
|
|
|
|
|
|
|
1874
|
|
|
|
|
|
|
When I<as_yaml> is True message text is a B<YAML::Dump()> of the |
|
1875
|
|
|
|
|
|
|
B<Carp::Proxy> object. Serialization via YAML makes it possible to |
|
1876
|
|
|
|
|
|
|
propagate exceptions up from child processes. |
|
1877
|
|
|
|
|
|
|
|
|
1878
|
|
|
|
|
|
|
=over 4 |
|
1879
|
|
|
|
|
|
|
|
|
1880
|
|
|
|
|
|
|
=item Builder: _build_as_yaml() |
|
1881
|
|
|
|
|
|
|
|
|
1882
|
|
|
|
|
|
|
=item Default: 0 (False) |
|
1883
|
|
|
|
|
|
|
|
|
1884
|
|
|
|
|
|
|
=item Domain: Boolean |
|
1885
|
|
|
|
|
|
|
|
|
1886
|
|
|
|
|
|
|
=item Affects: L<render_message()|/render_message> |
|
1887
|
|
|
|
|
|
|
|
|
1888
|
|
|
|
|
|
|
=item Mutability: Read-Write |
|
1889
|
|
|
|
|
|
|
|
|
1890
|
|
|
|
|
|
|
=back |
|
1891
|
|
|
|
|
|
|
|
|
1892
|
|
|
|
|
|
|
=head2 banner_title |
|
1893
|
|
|
|
|
|
|
|
|
1894
|
|
|
|
|
|
|
The Banner is the first part of the message; I<banner_title> contains the |
|
1895
|
|
|
|
|
|
|
first word(s) in the Banner. |
|
1896
|
|
|
|
|
|
|
|
|
1897
|
|
|
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
1898
|
|
|
|
|
|
|
Fatal << handler name >> |
|
1899
|
|
|
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
1900
|
|
|
|
|
|
|
----- |
|
1901
|
|
|
|
|
|
|
\ |
|
1902
|
|
|
|
|
|
|
+------ banner_title |
|
1903
|
|
|
|
|
|
|
|
|
1904
|
|
|
|
|
|
|
=over 4 |
|
1905
|
|
|
|
|
|
|
|
|
1906
|
|
|
|
|
|
|
=item Builder: _build_banner_title() |
|
1907
|
|
|
|
|
|
|
|
|
1908
|
|
|
|
|
|
|
=item Default: 'Fatal' |
|
1909
|
|
|
|
|
|
|
|
|
1910
|
|
|
|
|
|
|
=item Domain: String |
|
1911
|
|
|
|
|
|
|
|
|
1912
|
|
|
|
|
|
|
=item Affects: L<banner()|/banner> |
|
1913
|
|
|
|
|
|
|
|
|
1914
|
|
|
|
|
|
|
=item Mutability: Read-Write |
|
1915
|
|
|
|
|
|
|
|
|
1916
|
|
|
|
|
|
|
=back |
|
1917
|
|
|
|
|
|
|
|
|
1918
|
|
|
|
|
|
|
=head2 begin_hook |
|
1919
|
|
|
|
|
|
|
|
|
1920
|
|
|
|
|
|
|
If I<begin_hook> contains a CodeRef then the Proxy will call the CodeRef |
|
1921
|
|
|
|
|
|
|
immediately after constructing the B<Carp::Proxy> object. The object |
|
1922
|
|
|
|
|
|
|
is passed as the only argument. |
|
1923
|
|
|
|
|
|
|
|
|
1924
|
|
|
|
|
|
|
A I<begin_hook> is a great way to always do some activity at the start of |
|
1925
|
|
|
|
|
|
|
every exception - before any Handler gets control. |
|
1926
|
|
|
|
|
|
|
|
|
1927
|
|
|
|
|
|
|
=over 4 |
|
1928
|
|
|
|
|
|
|
|
|
1929
|
|
|
|
|
|
|
=item Builder: _build_begin_hook() |
|
1930
|
|
|
|
|
|
|
|
|
1931
|
|
|
|
|
|
|
=item Default: undef |
|
1932
|
|
|
|
|
|
|
|
|
1933
|
|
|
|
|
|
|
=item Domain: undef or a CodeRef |
|
1934
|
|
|
|
|
|
|
|
|
1935
|
|
|
|
|
|
|
=item Affects: L<PROXY-INVOCATION|/PROXY-INVOCATION:> |
|
1936
|
|
|
|
|
|
|
|
|
1937
|
|
|
|
|
|
|
=item Mutability: Read-Write |
|
1938
|
|
|
|
|
|
|
|
|
1939
|
|
|
|
|
|
|
=back |
|
1940
|
|
|
|
|
|
|
|
|
1941
|
|
|
|
|
|
|
=head2 body_indent |
|
1942
|
|
|
|
|
|
|
|
|
1943
|
|
|
|
|
|
|
I<body_indent> influences the presentation of paragraphs created |
|
1944
|
|
|
|
|
|
|
by the Section creating methods L<filled()|/filled> and |
|
1945
|
|
|
|
|
|
|
L<fixed()|/fixed>. Use I<body_indent> to determine the amount of |
|
1946
|
|
|
|
|
|
|
additional indentation, beyond L<header_indent|/header_indent>, |
|
1947
|
|
|
|
|
|
|
that is applied to Section paragraphs. |
|
1948
|
|
|
|
|
|
|
|
|
1949
|
|
|
|
|
|
|
=over 4 |
|
1950
|
|
|
|
|
|
|
|
|
1951
|
|
|
|
|
|
|
=item Builder: _build_body_indent() |
|
1952
|
|
|
|
|
|
|
|
|
1953
|
|
|
|
|
|
|
=item Default: 2 |
|
1954
|
|
|
|
|
|
|
|
|
1955
|
|
|
|
|
|
|
=item Domain: Non-negative integers |
|
1956
|
|
|
|
|
|
|
|
|
1957
|
|
|
|
|
|
|
=item Affects: L<filled_section()|/filled_section> and L<fixed_section()|/fixed_section> |
|
1958
|
|
|
|
|
|
|
|
|
1959
|
|
|
|
|
|
|
=item Mutability: Read-Write |
|
1960
|
|
|
|
|
|
|
|
|
1961
|
|
|
|
|
|
|
=back |
|
1962
|
|
|
|
|
|
|
|
|
1963
|
|
|
|
|
|
|
=head2 child_error |
|
1964
|
|
|
|
|
|
|
|
|
1965
|
|
|
|
|
|
|
I<child_error> holds the value of Perl's B<$CHILD_ERROR ($?)>, as harvested |
|
1966
|
|
|
|
|
|
|
from the invoking environment. |
|
1967
|
|
|
|
|
|
|
|
|
1968
|
|
|
|
|
|
|
=over 4 |
|
1969
|
|
|
|
|
|
|
|
|
1970
|
|
|
|
|
|
|
=item Builder: None; L<new()|/new> requires I<child_error> specification. |
|
1971
|
|
|
|
|
|
|
|
|
1972
|
|
|
|
|
|
|
=item Default: N/A |
|
1973
|
|
|
|
|
|
|
|
|
1974
|
|
|
|
|
|
|
=item Domain: Any |
|
1975
|
|
|
|
|
|
|
|
|
1976
|
|
|
|
|
|
|
=item Affects: L<decipher_child_error()|/decipher_child_error> |
|
1977
|
|
|
|
|
|
|
|
|
1978
|
|
|
|
|
|
|
=item Mutability: Read-Only |
|
1979
|
|
|
|
|
|
|
|
|
1980
|
|
|
|
|
|
|
=back |
|
1981
|
|
|
|
|
|
|
|
|
1982
|
|
|
|
|
|
|
=head2 columns |
|
1983
|
|
|
|
|
|
|
|
|
1984
|
|
|
|
|
|
|
The I<columns> attribute sets the line width target for the Banner and |
|
1985
|
|
|
|
|
|
|
for any filled Sections. Values below about 30 are not practical. |
|
1986
|
|
|
|
|
|
|
|
|
1987
|
|
|
|
|
|
|
=over 4 |
|
1988
|
|
|
|
|
|
|
|
|
1989
|
|
|
|
|
|
|
=item Builder: _build_columns() |
|
1990
|
|
|
|
|
|
|
|
|
1991
|
|
|
|
|
|
|
=item Default: 78 |
|
1992
|
|
|
|
|
|
|
|
|
1993
|
|
|
|
|
|
|
=item Domain: Positive Integers |
|
1994
|
|
|
|
|
|
|
|
|
1995
|
|
|
|
|
|
|
=item Affects: L<banner()|/banner> and L<filled_section()|/filled_section> |
|
1996
|
|
|
|
|
|
|
|
|
1997
|
|
|
|
|
|
|
=item Mutability: Read-Write |
|
1998
|
|
|
|
|
|
|
|
|
1999
|
|
|
|
|
|
|
=back |
|
2000
|
|
|
|
|
|
|
|
|
2001
|
|
|
|
|
|
|
=head2 context |
|
2002
|
|
|
|
|
|
|
|
|
2003
|
|
|
|
|
|
|
The I<context> attribute controls the generation of a stacktrace Section. |
|
2004
|
|
|
|
|
|
|
|
|
2005
|
|
|
|
|
|
|
=over 4 |
|
2006
|
|
|
|
|
|
|
|
|
2007
|
|
|
|
|
|
|
=item Builder: _build_context() |
|
2008
|
|
|
|
|
|
|
|
|
2009
|
|
|
|
|
|
|
=item Default: 'confess' |
|
2010
|
|
|
|
|
|
|
|
|
2011
|
|
|
|
|
|
|
=item Domain: |
|
2012
|
|
|
|
|
|
|
|
|
2013
|
|
|
|
|
|
|
=over 4 |
|
2014
|
|
|
|
|
|
|
|
|
2015
|
|
|
|
|
|
|
=item 'none' - No Section generated. |
|
2016
|
|
|
|
|
|
|
|
|
2017
|
|
|
|
|
|
|
=item 'die' - Describe where Proxy was called. |
|
2018
|
|
|
|
|
|
|
|
|
2019
|
|
|
|
|
|
|
=item 'croak' - Describe where Proxy's caller was called. |
|
2020
|
|
|
|
|
|
|
|
|
2021
|
|
|
|
|
|
|
=item 'confess' - Stacktrace, starting with Proxy call. |
|
2022
|
|
|
|
|
|
|
|
|
2023
|
|
|
|
|
|
|
=item 'internals' - Complete stacktrace with Carp::Proxy guts. |
|
2024
|
|
|
|
|
|
|
|
|
2025
|
|
|
|
|
|
|
=item CodeRef - Do it yourself. |
|
2026
|
|
|
|
|
|
|
|
|
2027
|
|
|
|
|
|
|
=back |
|
2028
|
|
|
|
|
|
|
|
|
2029
|
|
|
|
|
|
|
=item Affects: L<add_context()|/add_context> |
|
2030
|
|
|
|
|
|
|
|
|
2031
|
|
|
|
|
|
|
=item Mutability: Read-Write |
|
2032
|
|
|
|
|
|
|
|
|
2033
|
|
|
|
|
|
|
=back |
|
2034
|
|
|
|
|
|
|
|
|
2035
|
|
|
|
|
|
|
=head2 disposition |
|
2036
|
|
|
|
|
|
|
|
|
2037
|
|
|
|
|
|
|
The I<disposition> attribute controls how the exception is thrown. |
|
2038
|
|
|
|
|
|
|
|
|
2039
|
|
|
|
|
|
|
=over 4 |
|
2040
|
|
|
|
|
|
|
|
|
2041
|
|
|
|
|
|
|
=item Builder: _build_disposition() |
|
2042
|
|
|
|
|
|
|
|
|
2043
|
|
|
|
|
|
|
=item Default: 'die' |
|
2044
|
|
|
|
|
|
|
|
|
2045
|
|
|
|
|
|
|
=item Domain: |
|
2046
|
|
|
|
|
|
|
|
|
2047
|
|
|
|
|
|
|
=over 4 |
|
2048
|
|
|
|
|
|
|
|
|
2049
|
|
|
|
|
|
|
=item 'return' - No exception thrown; Proxy returns. |
|
2050
|
|
|
|
|
|
|
|
|
2051
|
|
|
|
|
|
|
=item 'warn' - Carp::Proxy object passed to Perl's B<warn()>. |
|
2052
|
|
|
|
|
|
|
|
|
2053
|
|
|
|
|
|
|
=item 'die' - Carp::Proxy object passed to Perl's B<die()>. |
|
2054
|
|
|
|
|
|
|
|
|
2055
|
|
|
|
|
|
|
=item CodeRef - Do it yourself. |
|
2056
|
|
|
|
|
|
|
|
|
2057
|
|
|
|
|
|
|
=back |
|
2058
|
|
|
|
|
|
|
|
|
2059
|
|
|
|
|
|
|
=item Affects: L<perform_disposition()|/perform_disposition> |
|
2060
|
|
|
|
|
|
|
|
|
2061
|
|
|
|
|
|
|
=item Mutability: Read-Write |
|
2062
|
|
|
|
|
|
|
|
|
2063
|
|
|
|
|
|
|
=back |
|
2064
|
|
|
|
|
|
|
|
|
2065
|
|
|
|
|
|
|
=head2 end_hook |
|
2066
|
|
|
|
|
|
|
|
|
2067
|
|
|
|
|
|
|
If I<end_hook> contains a CodeRef then the Proxy will call the CodeRef |
|
2068
|
|
|
|
|
|
|
just before performing disposition. The B<Carp::Proxy> object is |
|
2069
|
|
|
|
|
|
|
passed as the only argument. |
|
2070
|
|
|
|
|
|
|
|
|
2071
|
|
|
|
|
|
|
The I<end_hook> is handy for things that you want all Handlers to do as |
|
2072
|
|
|
|
|
|
|
their last action. An example might be writing to a logfile. |
|
2073
|
|
|
|
|
|
|
|
|
2074
|
|
|
|
|
|
|
=over 4 |
|
2075
|
|
|
|
|
|
|
|
|
2076
|
|
|
|
|
|
|
=item Builder: _build_end_hook() |
|
2077
|
|
|
|
|
|
|
|
|
2078
|
|
|
|
|
|
|
=item Default: undef |
|
2079
|
|
|
|
|
|
|
|
|
2080
|
|
|
|
|
|
|
=item Domain: undef or a CodeRef |
|
2081
|
|
|
|
|
|
|
|
|
2082
|
|
|
|
|
|
|
=item Affects: L<PROXY-INVOCATION|/PROXY-INVOCATION:> |
|
2083
|
|
|
|
|
|
|
|
|
2084
|
|
|
|
|
|
|
=item Mutability: Read-Write |
|
2085
|
|
|
|
|
|
|
|
|
2086
|
|
|
|
|
|
|
=back |
|
2087
|
|
|
|
|
|
|
|
|
2088
|
|
|
|
|
|
|
=head2 eval_error |
|
2089
|
|
|
|
|
|
|
|
|
2090
|
|
|
|
|
|
|
The I<eval_error> attribute holds the value of Perl's B<$EVAL_ERROR ($@)>, |
|
2091
|
|
|
|
|
|
|
as harvested from the invoking environment. |
|
2092
|
|
|
|
|
|
|
|
|
2093
|
|
|
|
|
|
|
=over 4 |
|
2094
|
|
|
|
|
|
|
|
|
2095
|
|
|
|
|
|
|
=item Builder: None; L<new()|/new> requires an I<eval_error> specification |
|
2096
|
|
|
|
|
|
|
|
|
2097
|
|
|
|
|
|
|
=item Default: N/A |
|
2098
|
|
|
|
|
|
|
|
|
2099
|
|
|
|
|
|
|
=item Domain: Any |
|
2100
|
|
|
|
|
|
|
|
|
2101
|
|
|
|
|
|
|
=item Affects: For user convenience; not used by B<Carp::Proxy> |
|
2102
|
|
|
|
|
|
|
|
|
2103
|
|
|
|
|
|
|
=item Mutability: Read-Only |
|
2104
|
|
|
|
|
|
|
|
|
2105
|
|
|
|
|
|
|
=back |
|
2106
|
|
|
|
|
|
|
|
|
2107
|
|
|
|
|
|
|
=head2 exit_code |
|
2108
|
|
|
|
|
|
|
|
|
2109
|
|
|
|
|
|
|
I<exit_code> is used to set the value harvested by the operating system |
|
2110
|
|
|
|
|
|
|
when a process dies. |
|
2111
|
|
|
|
|
|
|
|
|
2112
|
|
|
|
|
|
|
=over 4 |
|
2113
|
|
|
|
|
|
|
|
|
2114
|
|
|
|
|
|
|
=item Builder: _build_exit_code() |
|
2115
|
|
|
|
|
|
|
|
|
2116
|
|
|
|
|
|
|
=item Default: 1 |
|
2117
|
|
|
|
|
|
|
|
|
2118
|
|
|
|
|
|
|
=item Domain: Integers greater than Zero |
|
2119
|
|
|
|
|
|
|
|
|
2120
|
|
|
|
|
|
|
=item Affects: L<perform_disposition()|/perform_disposition> |
|
2121
|
|
|
|
|
|
|
|
|
2122
|
|
|
|
|
|
|
=item Mutability: Read-Write |
|
2123
|
|
|
|
|
|
|
|
|
2124
|
|
|
|
|
|
|
=back |
|
2125
|
|
|
|
|
|
|
|
|
2126
|
|
|
|
|
|
|
=head2 fq_proxy_name |
|
2127
|
|
|
|
|
|
|
|
|
2128
|
|
|
|
|
|
|
I<fq_proxy_name> is the fully-qualified proxy-name. This is the Proxy's |
|
2129
|
|
|
|
|
|
|
name, complete with exported package qualifier. This might be useful if |
|
2130
|
|
|
|
|
|
|
a Handler wants to know the parental Proxy. |
|
2131
|
|
|
|
|
|
|
|
|
2132
|
|
|
|
|
|
|
=over 4 |
|
2133
|
|
|
|
|
|
|
|
|
2134
|
|
|
|
|
|
|
=item Builder: None; L<new()|/new> requires I<fq_proxy_name> specification |
|
2135
|
|
|
|
|
|
|
|
|
2136
|
|
|
|
|
|
|
=item Default: N/A |
|
2137
|
|
|
|
|
|
|
|
|
2138
|
|
|
|
|
|
|
=item Domain: String |
|
2139
|
|
|
|
|
|
|
|
|
2140
|
|
|
|
|
|
|
=item Affects: L<add_context()|/add_context> |
|
2141
|
|
|
|
|
|
|
|
|
2142
|
|
|
|
|
|
|
=item Mutability: Read-Write |
|
2143
|
|
|
|
|
|
|
|
|
2144
|
|
|
|
|
|
|
=back |
|
2145
|
|
|
|
|
|
|
|
|
2146
|
|
|
|
|
|
|
=head2 handler_name |
|
2147
|
|
|
|
|
|
|
|
|
2148
|
|
|
|
|
|
|
The Proxy saves its first argument, the Handler, in I<handler_name>. |
|
2149
|
|
|
|
|
|
|
|
|
2150
|
|
|
|
|
|
|
=over 4 |
|
2151
|
|
|
|
|
|
|
|
|
2152
|
|
|
|
|
|
|
=item Builder: None; L<new()|/new> requires I<handler_name> specification |
|
2153
|
|
|
|
|
|
|
|
|
2154
|
|
|
|
|
|
|
=item Default: N/A |
|
2155
|
|
|
|
|
|
|
|
|
2156
|
|
|
|
|
|
|
=item Domain: String |
|
2157
|
|
|
|
|
|
|
|
|
2158
|
|
|
|
|
|
|
=item Affects: L<banner()|/banner>, L<HANDLER SEARCH|/HANDLER-SEARCH:> |
|
2159
|
|
|
|
|
|
|
|
|
2160
|
|
|
|
|
|
|
=item Mutability: Read-Write |
|
2161
|
|
|
|
|
|
|
|
|
2162
|
|
|
|
|
|
|
=back |
|
2163
|
|
|
|
|
|
|
|
|
2164
|
|
|
|
|
|
|
=head2 handler_pkgs |
|
2165
|
|
|
|
|
|
|
|
|
2166
|
|
|
|
|
|
|
The search for a Handler subroutine is performed in each of the packages |
|
2167
|
|
|
|
|
|
|
in the ArrayRef I<handler_pkgs>. A copy of |
|
2168
|
|
|
|
|
|
|
L<proxy_package|/proxy_package> is automatically appended, by |
|
2169
|
|
|
|
|
|
|
the Proxy after object construction. |
|
2170
|
|
|
|
|
|
|
|
|
2171
|
|
|
|
|
|
|
=over 4 |
|
2172
|
|
|
|
|
|
|
|
|
2173
|
|
|
|
|
|
|
=item Builder: _build_handler_pkgs() |
|
2174
|
|
|
|
|
|
|
|
|
2175
|
|
|
|
|
|
|
=item Default: [] |
|
2176
|
|
|
|
|
|
|
|
|
2177
|
|
|
|
|
|
|
=item Domain: ArrayRef |
|
2178
|
|
|
|
|
|
|
|
|
2179
|
|
|
|
|
|
|
=item Affects: L<HANDLER SEARCH|/HANDLER-SEARCH:> |
|
2180
|
|
|
|
|
|
|
|
|
2181
|
|
|
|
|
|
|
=item Mutability: Read-Write |
|
2182
|
|
|
|
|
|
|
|
|
2183
|
|
|
|
|
|
|
=back |
|
2184
|
|
|
|
|
|
|
|
|
2185
|
|
|
|
|
|
|
=head2 handler_prefix |
|
2186
|
|
|
|
|
|
|
|
|
2187
|
|
|
|
|
|
|
I<handler_prefix> affects how the search for a Handler is performed. |
|
2188
|
|
|
|
|
|
|
The list of templates that are tried during L<HANDLER SEARCH|/HANDLER-SEARCH:> |
|
2189
|
|
|
|
|
|
|
is based on I<handler_prefix>. |
|
2190
|
|
|
|
|
|
|
|
|
2191
|
|
|
|
|
|
|
=over 4 |
|
2192
|
|
|
|
|
|
|
|
|
2193
|
|
|
|
|
|
|
=item Builder: _build_handler_prefix() |
|
2194
|
|
|
|
|
|
|
|
|
2195
|
|
|
|
|
|
|
=item Default: undef |
|
2196
|
|
|
|
|
|
|
|
|
2197
|
|
|
|
|
|
|
=item Domain: undef or String |
|
2198
|
|
|
|
|
|
|
|
|
2199
|
|
|
|
|
|
|
=item Affects: L<HANDLER SEARCH|/HANDLER-SEARCH:> |
|
2200
|
|
|
|
|
|
|
|
|
2201
|
|
|
|
|
|
|
=item Mutability: Read-Write |
|
2202
|
|
|
|
|
|
|
|
|
2203
|
|
|
|
|
|
|
=back |
|
2204
|
|
|
|
|
|
|
|
|
2205
|
|
|
|
|
|
|
=head2 header_indent |
|
2206
|
|
|
|
|
|
|
|
|
2207
|
|
|
|
|
|
|
Section Headers are indented from the left margin by I<header_indent> |
|
2208
|
|
|
|
|
|
|
spaces. |
|
2209
|
|
|
|
|
|
|
|
|
2210
|
|
|
|
|
|
|
=over 4 |
|
2211
|
|
|
|
|
|
|
|
|
2212
|
|
|
|
|
|
|
=item Builder: _build_header_indent() |
|
2213
|
|
|
|
|
|
|
|
|
2214
|
|
|
|
|
|
|
=item Default: 2 |
|
2215
|
|
|
|
|
|
|
|
|
2216
|
|
|
|
|
|
|
=item Domain: Non-negative Integers |
|
2217
|
|
|
|
|
|
|
|
|
2218
|
|
|
|
|
|
|
=item Affects: L<header()|/header>, L<filled_section()|/filled_section> L<fixed_section()|/fixed_section> |
|
2219
|
|
|
|
|
|
|
|
|
2220
|
|
|
|
|
|
|
=item Mutability: Read-Write |
|
2221
|
|
|
|
|
|
|
|
|
2222
|
|
|
|
|
|
|
=back |
|
2223
|
|
|
|
|
|
|
|
|
2224
|
|
|
|
|
|
|
=head2 maintainer |
|
2225
|
|
|
|
|
|
|
|
|
2226
|
|
|
|
|
|
|
The L<contact_maintainer()|/contact_maintainer> method produces a |
|
2227
|
|
|
|
|
|
|
Section that urges the message recipient to contact the maintainer. The |
|
2228
|
|
|
|
|
|
|
Section is created only if the I<maintainer> attribute is non-empty. A |
|
2229
|
|
|
|
|
|
|
string containing an email address and a telephone number works well. |
|
2230
|
|
|
|
|
|
|
|
|
2231
|
|
|
|
|
|
|
=over 4 |
|
2232
|
|
|
|
|
|
|
|
|
2233
|
|
|
|
|
|
|
=item Builder: _build_maintainer() |
|
2234
|
|
|
|
|
|
|
|
|
2235
|
|
|
|
|
|
|
=item Default: '' |
|
2236
|
|
|
|
|
|
|
|
|
2237
|
|
|
|
|
|
|
=item Domain: String |
|
2238
|
|
|
|
|
|
|
|
|
2239
|
|
|
|
|
|
|
=item Affects: L<contact_maintainer()|/contact_maintainer> |
|
2240
|
|
|
|
|
|
|
|
|
2241
|
|
|
|
|
|
|
=item Mutability: Read-Write |
|
2242
|
|
|
|
|
|
|
|
|
2243
|
|
|
|
|
|
|
=back |
|
2244
|
|
|
|
|
|
|
|
|
2245
|
|
|
|
|
|
|
=head2 numeric_errno |
|
2246
|
|
|
|
|
|
|
|
|
2247
|
|
|
|
|
|
|
The I<numeric_errno> attribute contains the value of |
|
2248
|
|
|
|
|
|
|
Perl's B<$ERRNO ($!)>, as harvested from the invoking environment. The |
|
2249
|
|
|
|
|
|
|
value is obtained by evaluating B<$ERRNO> in a numeric context. |
|
2250
|
|
|
|
|
|
|
|
|
2251
|
|
|
|
|
|
|
=over 4 |
|
2252
|
|
|
|
|
|
|
|
|
2253
|
|
|
|
|
|
|
=item Builder: None; L<new()|/new> requires I<numeric_errno> specification |
|
2254
|
|
|
|
|
|
|
|
|
2255
|
|
|
|
|
|
|
=item Default: N/A |
|
2256
|
|
|
|
|
|
|
|
|
2257
|
|
|
|
|
|
|
=item Domain: Any |
|
2258
|
|
|
|
|
|
|
|
|
2259
|
|
|
|
|
|
|
=item Affects: For user convenience; not used by B<Carp::Proxy> |
|
2260
|
|
|
|
|
|
|
|
|
2261
|
|
|
|
|
|
|
=item Mutability: Read-Only |
|
2262
|
|
|
|
|
|
|
|
|
2263
|
|
|
|
|
|
|
=back |
|
2264
|
|
|
|
|
|
|
|
|
2265
|
|
|
|
|
|
|
=head2 pod_filename |
|
2266
|
|
|
|
|
|
|
|
|
2267
|
|
|
|
|
|
|
The L<synopsis()|/synopsis> method searches for POD in |
|
2268
|
|
|
|
|
|
|
I<pod_filename>. |
|
2269
|
|
|
|
|
|
|
|
|
2270
|
|
|
|
|
|
|
=over 4 |
|
2271
|
|
|
|
|
|
|
|
|
2272
|
|
|
|
|
|
|
=item Builder: _build_pod_filename() |
|
2273
|
|
|
|
|
|
|
|
|
2274
|
|
|
|
|
|
|
=item Default: L<proxy_filename|/proxy_filename>. |
|
2275
|
|
|
|
|
|
|
|
|
2276
|
|
|
|
|
|
|
=item Domain: String |
|
2277
|
|
|
|
|
|
|
|
|
2278
|
|
|
|
|
|
|
=item Affects: L<synopsis()|/synopsis> |
|
2279
|
|
|
|
|
|
|
|
|
2280
|
|
|
|
|
|
|
=item Mutability: Read-Write |
|
2281
|
|
|
|
|
|
|
|
|
2282
|
|
|
|
|
|
|
=back |
|
2283
|
|
|
|
|
|
|
|
|
2284
|
|
|
|
|
|
|
=head2 proxy_filename |
|
2285
|
|
|
|
|
|
|
|
|
2286
|
|
|
|
|
|
|
The filename containing the code that requested construction of the Proxy, |
|
2287
|
|
|
|
|
|
|
either by B<use()> or L<import()|/import>. |
|
2288
|
|
|
|
|
|
|
|
|
2289
|
|
|
|
|
|
|
=over 4 |
|
2290
|
|
|
|
|
|
|
|
|
2291
|
|
|
|
|
|
|
=item Builder: None; L<new()|/new> requires I<proxy_filename> specification |
|
2292
|
|
|
|
|
|
|
|
|
2293
|
|
|
|
|
|
|
=item Default: N/A |
|
2294
|
|
|
|
|
|
|
|
|
2295
|
|
|
|
|
|
|
=item Domain: String |
|
2296
|
|
|
|
|
|
|
|
|
2297
|
|
|
|
|
|
|
=item Affects: L<pod_filename|/pod_filename>. |
|
2298
|
|
|
|
|
|
|
|
|
2299
|
|
|
|
|
|
|
=item Mutability: Read-Only |
|
2300
|
|
|
|
|
|
|
|
|
2301
|
|
|
|
|
|
|
=back |
|
2302
|
|
|
|
|
|
|
|
|
2303
|
|
|
|
|
|
|
=head2 proxy_name |
|
2304
|
|
|
|
|
|
|
|
|
2305
|
|
|
|
|
|
|
I<proxy_name> contains the name of the Proxy subroutine. |
|
2306
|
|
|
|
|
|
|
|
|
2307
|
|
|
|
|
|
|
The default I<proxy_name> is B<'fatal'>. |
|
2308
|
|
|
|
|
|
|
|
|
2309
|
|
|
|
|
|
|
The only time this attribute is used is when B<use()> or L<import()|/import> |
|
2310
|
|
|
|
|
|
|
are called without arguments. Defining a B<_build_proxy_name()> in |
|
2311
|
|
|
|
|
|
|
a sub class allows you to change the default name. |
|
2312
|
|
|
|
|
|
|
|
|
2313
|
|
|
|
|
|
|
=over 4 |
|
2314
|
|
|
|
|
|
|
|
|
2315
|
|
|
|
|
|
|
=item Builder: _build_proxy_name(); L<new()|/new> requires I<proxy_name> |
|
2316
|
|
|
|
|
|
|
|
|
2317
|
|
|
|
|
|
|
=item Default: 'fatal' |
|
2318
|
|
|
|
|
|
|
|
|
2319
|
|
|
|
|
|
|
=item Domain: String |
|
2320
|
|
|
|
|
|
|
|
|
2321
|
|
|
|
|
|
|
=item Affects: B<use()>, L<import()|/import> |
|
2322
|
|
|
|
|
|
|
|
|
2323
|
|
|
|
|
|
|
=item Mutability: Read-Only |
|
2324
|
|
|
|
|
|
|
|
|
2325
|
|
|
|
|
|
|
=back |
|
2326
|
|
|
|
|
|
|
|
|
2327
|
|
|
|
|
|
|
=head2 proxy_package |
|
2328
|
|
|
|
|
|
|
|
|
2329
|
|
|
|
|
|
|
The I<proxy_package> attribute is derived from the package that requested |
|
2330
|
|
|
|
|
|
|
construction of the Proxy, either by calling B<use()> or L<import()|/import>. |
|
2331
|
|
|
|
|
|
|
|
|
2332
|
|
|
|
|
|
|
=over 4 |
|
2333
|
|
|
|
|
|
|
|
|
2334
|
|
|
|
|
|
|
=item Builder: None; L<new()|/new> requires I<proxy_package> specification |
|
2335
|
|
|
|
|
|
|
|
|
2336
|
|
|
|
|
|
|
=item Default: Package of whatever subroutine called B<use()> or L<import()|/import> |
|
2337
|
|
|
|
|
|
|
|
|
2338
|
|
|
|
|
|
|
=item Domain: String |
|
2339
|
|
|
|
|
|
|
|
|
2340
|
|
|
|
|
|
|
=item Affects: L<handler_pkgs|/handler_pkgs> |
|
2341
|
|
|
|
|
|
|
|
|
2342
|
|
|
|
|
|
|
=item Mutability: Read-Only |
|
2343
|
|
|
|
|
|
|
|
|
2344
|
|
|
|
|
|
|
=back |
|
2345
|
|
|
|
|
|
|
|
|
2346
|
|
|
|
|
|
|
=head2 section_title |
|
2347
|
|
|
|
|
|
|
|
|
2348
|
|
|
|
|
|
|
The Section-creating methods L<filled()|/filled> and |
|
2349
|
|
|
|
|
|
|
L<fixed()|/fixed>, accept an optional, second argument to be used |
|
2350
|
|
|
|
|
|
|
as the title for the Section. When this optional argument is not |
|
2351
|
|
|
|
|
|
|
supplied, I<section_title> is used instead. |
|
2352
|
|
|
|
|
|
|
|
|
2353
|
|
|
|
|
|
|
=over 4 |
|
2354
|
|
|
|
|
|
|
|
|
2355
|
|
|
|
|
|
|
=item Builder: _build_section_title() |
|
2356
|
|
|
|
|
|
|
|
|
2357
|
|
|
|
|
|
|
=item Default: 'Description' |
|
2358
|
|
|
|
|
|
|
|
|
2359
|
|
|
|
|
|
|
=item Domain: Non-empty String |
|
2360
|
|
|
|
|
|
|
|
|
2361
|
|
|
|
|
|
|
=item Affects: L<header()|/header>, L<filled()|/filled>, L<fixed()|/fixed> |
|
2362
|
|
|
|
|
|
|
|
|
2363
|
|
|
|
|
|
|
=item Mutability: Read-Write |
|
2364
|
|
|
|
|
|
|
|
|
2365
|
|
|
|
|
|
|
=back |
|
2366
|
|
|
|
|
|
|
|
|
2367
|
|
|
|
|
|
|
=head2 sections |
|
2368
|
|
|
|
|
|
|
|
|
2369
|
|
|
|
|
|
|
The Section-creating methods L<filled()|/filled>, |
|
2370
|
|
|
|
|
|
|
L<fixed()|/fixed> and L<raw()|/raw> create Section |
|
2371
|
|
|
|
|
|
|
specifications. Section specifications accumulate in the ArrayRef |
|
2372
|
|
|
|
|
|
|
I<sections>. |
|
2373
|
|
|
|
|
|
|
|
|
2374
|
|
|
|
|
|
|
=over 4 |
|
2375
|
|
|
|
|
|
|
|
|
2376
|
|
|
|
|
|
|
=item Builder: _build_sections() |
|
2377
|
|
|
|
|
|
|
|
|
2378
|
|
|
|
|
|
|
=item Default: [] |
|
2379
|
|
|
|
|
|
|
|
|
2380
|
|
|
|
|
|
|
=item Domain: ArrayRef of section-specifications |
|
2381
|
|
|
|
|
|
|
|
|
2382
|
|
|
|
|
|
|
=item Affects: L<render_message()|/render_message> |
|
2383
|
|
|
|
|
|
|
|
|
2384
|
|
|
|
|
|
|
=item Mutability: Read-Write |
|
2385
|
|
|
|
|
|
|
|
|
2386
|
|
|
|
|
|
|
=back |
|
2387
|
|
|
|
|
|
|
|
|
2388
|
|
|
|
|
|
|
=head2 string_errno |
|
2389
|
|
|
|
|
|
|
|
|
2390
|
|
|
|
|
|
|
I<string_errno> is a read-only attribute that contains the value of Perl's |
|
2391
|
|
|
|
|
|
|
B<$ERRNO ($!)>, harvested from the invoking environment. The value is |
|
2392
|
|
|
|
|
|
|
obtained by evaluating B<$ERRNO> in a string context. |
|
2393
|
|
|
|
|
|
|
|
|
2394
|
|
|
|
|
|
|
=over 4 |
|
2395
|
|
|
|
|
|
|
|
|
2396
|
|
|
|
|
|
|
=item Builder: None; L<new()|/new> requires I<string_errno> specification |
|
2397
|
|
|
|
|
|
|
|
|
2398
|
|
|
|
|
|
|
=item Default: N/A |
|
2399
|
|
|
|
|
|
|
|
|
2400
|
|
|
|
|
|
|
=item Domain: String |
|
2401
|
|
|
|
|
|
|
|
|
2402
|
|
|
|
|
|
|
=item Affects: L<errno_section()|/errno_section> |
|
2403
|
|
|
|
|
|
|
|
|
2404
|
|
|
|
|
|
|
=item Mutability: Read-Only |
|
2405
|
|
|
|
|
|
|
|
|
2406
|
|
|
|
|
|
|
=back |
|
2407
|
|
|
|
|
|
|
|
|
2408
|
|
|
|
|
|
|
=head2 tags |
|
2409
|
|
|
|
|
|
|
|
|
2410
|
|
|
|
|
|
|
Passing arbitrary data to the catching environment can sometimes be |
|
2411
|
|
|
|
|
|
|
useful. The I<tags> attribute is a HashRef for tag-value pairs of user |
|
2412
|
|
|
|
|
|
|
data. The attribute is completely ignored by the Proxy and by |
|
2413
|
|
|
|
|
|
|
B<Carp::Proxy> methods. |
|
2414
|
|
|
|
|
|
|
|
|
2415
|
|
|
|
|
|
|
=over 4 |
|
2416
|
|
|
|
|
|
|
|
|
2417
|
|
|
|
|
|
|
=item Builder: _build_tags() |
|
2418
|
|
|
|
|
|
|
|
|
2419
|
|
|
|
|
|
|
=item Default: {} |
|
2420
|
|
|
|
|
|
|
|
|
2421
|
|
|
|
|
|
|
=item Domain: HashRef |
|
2422
|
|
|
|
|
|
|
|
|
2423
|
|
|
|
|
|
|
=item Affects: For user convenience; not used by B<Carp::Proxy> |
|
2424
|
|
|
|
|
|
|
|
|
2425
|
|
|
|
|
|
|
=item Mutability: Read-Write |
|
2426
|
|
|
|
|
|
|
|
|
2427
|
|
|
|
|
|
|
=back |
|
2428
|
|
|
|
|
|
|
|
|
2429
|
|
|
|
|
|
|
=head1 METHODS |
|
2430
|
|
|
|
|
|
|
|
|
2431
|
|
|
|
|
|
|
The documentation for each method starts off with a 'Usage' description. |
|
2432
|
|
|
|
|
|
|
A description will look something like this: |
|
2433
|
|
|
|
|
|
|
|
|
2434
|
|
|
|
|
|
|
Usage: |
|
2435
|
|
|
|
|
|
|
<void> $cp->append_handler_package( $pkg <, $pkg2 ...>); |
|
2436
|
|
|
|
|
|
|
|
|
2437
|
|
|
|
|
|
|
The word enclosed in angle-brackets, at the beginning, (Like |
|
2438
|
|
|
|
|
|
|
B<E<lt>voidE<gt>>) attempts to convey the return value. Arguments in |
|
2439
|
|
|
|
|
|
|
angle-brackets are optional, with the ellipsis (B<...>) implying |
|
2440
|
|
|
|
|
|
|
repeatability. B<$cp> is a B<Carp::Proxy> object. B<$class>, if used as |
|
2441
|
|
|
|
|
|
|
the invoker, indicates a class method. |
|
2442
|
|
|
|
|
|
|
|
|
2443
|
|
|
|
|
|
|
=head2 add_context |
|
2444
|
|
|
|
|
|
|
|
|
2445
|
|
|
|
|
|
|
Usage: |
|
2446
|
|
|
|
|
|
|
<void> $cp->add_context(); |
|
2447
|
|
|
|
|
|
|
|
|
2448
|
|
|
|
|
|
|
B<add_context()> creates a Section that contains a stacktrace of where the |
|
2449
|
|
|
|
|
|
|
Proxy was invoked. The L<context|/context> attribute controls |
|
2450
|
|
|
|
|
|
|
whether or not the Section is generated, as well as what kind of |
|
2451
|
|
|
|
|
|
|
stacktrace is produced. |
|
2452
|
|
|
|
|
|
|
|
|
2453
|
|
|
|
|
|
|
B<add_context()> is called by the Proxy when the Handler returns. |
|
2454
|
|
|
|
|
|
|
|
|
2455
|
|
|
|
|
|
|
Perl's B<caller()> is used to probe the callstack and report stackframes. |
|
2456
|
|
|
|
|
|
|
Stackframes are rendered on one line if the length would not exceed the |
|
2457
|
|
|
|
|
|
|
value of the L<columns|/columns> attribute. Long lines are |
|
2458
|
|
|
|
|
|
|
folded at the filename portion of the stackframe and given |
|
2459
|
|
|
|
|
|
|
L<body_indent|/body_indent> extra spaces of indentation. |
|
2460
|
|
|
|
|
|
|
|
|
2461
|
|
|
|
|
|
|
The L<context|/context> attribute may take on any of these |
|
2462
|
|
|
|
|
|
|
values: |
|
2463
|
|
|
|
|
|
|
|
|
2464
|
|
|
|
|
|
|
=over 4 |
|
2465
|
|
|
|
|
|
|
|
|
2466
|
|
|
|
|
|
|
=item B<'none'> |
|
2467
|
|
|
|
|
|
|
|
|
2468
|
|
|
|
|
|
|
The I<context> of C<'none'> is a request to forego stacktrace generation. |
|
2469
|
|
|
|
|
|
|
No Section is produced. |
|
2470
|
|
|
|
|
|
|
|
|
2471
|
|
|
|
|
|
|
=item B<'die'> |
|
2472
|
|
|
|
|
|
|
|
|
2473
|
|
|
|
|
|
|
The I<context> of C<'die'> adds a Section containing a single entry. The |
|
2474
|
|
|
|
|
|
|
entry details the source location where the Proxy was invoked. The effect |
|
2475
|
|
|
|
|
|
|
is intended to mimic Perl's behavior when B<die()> is passed a string |
|
2476
|
|
|
|
|
|
|
WITHOUT a trailing newline. |
|
2477
|
|
|
|
|
|
|
|
|
2478
|
|
|
|
|
|
|
The title for the Section is C<'Exception'>. |
|
2479
|
|
|
|
|
|
|
|
|
2480
|
|
|
|
|
|
|
*** Exception *** |
|
2481
|
|
|
|
|
|
|
fatal called from line 27 of /home/duane/bin/assim |
|
2482
|
|
|
|
|
|
|
|
|
2483
|
|
|
|
|
|
|
=item B<'croak'> |
|
2484
|
|
|
|
|
|
|
|
|
2485
|
|
|
|
|
|
|
The I<context> of C<'croak'> adds a Section that identifies the subroutine |
|
2486
|
|
|
|
|
|
|
that invoked the Proxy. The effect is intended to mimic the behavior of |
|
2487
|
|
|
|
|
|
|
B<Carp::croak()>, which assigns blame to the caller. |
|
2488
|
|
|
|
|
|
|
|
|
2489
|
|
|
|
|
|
|
The title for the Section is C<'Exception'>. |
|
2490
|
|
|
|
|
|
|
|
|
2491
|
|
|
|
|
|
|
*** Exception *** |
|
2492
|
|
|
|
|
|
|
perform_query called from line 1172 of |
|
2493
|
|
|
|
|
|
|
/opt/barkta/linux/v3.7/bin/ReadRecords |
|
2494
|
|
|
|
|
|
|
|
|
2495
|
|
|
|
|
|
|
=item B<'confess'> |
|
2496
|
|
|
|
|
|
|
|
|
2497
|
|
|
|
|
|
|
The I<context> setting of C<'confess'> creates a multi-line Section. |
|
2498
|
|
|
|
|
|
|
Lines in the Section correspond to stackframes from nearest to outermost, |
|
2499
|
|
|
|
|
|
|
much like the behavior of B<Carp::confess>. |
|
2500
|
|
|
|
|
|
|
|
|
2501
|
|
|
|
|
|
|
C<'confess'> is the default I<context> for B<Carp::Proxy> objects. |
|
2502
|
|
|
|
|
|
|
|
|
2503
|
|
|
|
|
|
|
The Section title is 'Stacktrace'. |
|
2504
|
|
|
|
|
|
|
|
|
2505
|
|
|
|
|
|
|
=item B<'internals'> |
|
2506
|
|
|
|
|
|
|
|
|
2507
|
|
|
|
|
|
|
The I<context> setting C<'internals'> is very similar to the setting |
|
2508
|
|
|
|
|
|
|
C<'confess'>. Both produce full stacktraces, but C<'confess'> omits |
|
2509
|
|
|
|
|
|
|
stackframes that originate on behalf of the Proxy. You normally do |
|
2510
|
|
|
|
|
|
|
not want to see B<Carp::Proxy> stackframes, although they might be helpful |
|
2511
|
|
|
|
|
|
|
in debugging a sub-class. C<'internals'> gives you everything. |
|
2512
|
|
|
|
|
|
|
|
|
2513
|
|
|
|
|
|
|
The Section title is 'Stacktrace'. |
|
2514
|
|
|
|
|
|
|
|
|
2515
|
|
|
|
|
|
|
=item B<CodeRef> |
|
2516
|
|
|
|
|
|
|
|
|
2517
|
|
|
|
|
|
|
By providing a CodeRef users can completely control context reporting. |
|
2518
|
|
|
|
|
|
|
|
|
2519
|
|
|
|
|
|
|
The Proxy will make a callback to I<CodeRef> immediately after the Handler |
|
2520
|
|
|
|
|
|
|
returns. The B<Carp::Proxy> object will be passed as the only argument. |
|
2521
|
|
|
|
|
|
|
The CodeRef should create a Section using the L<filled()|/filled>, |
|
2522
|
|
|
|
|
|
|
L<fixed()|/fixed> or L<raw()|/raw> methods. |
|
2523
|
|
|
|
|
|
|
|
|
2524
|
|
|
|
|
|
|
The B<Carp> module from the Perl standard library provides some complex |
|
2525
|
|
|
|
|
|
|
functionality for ignoring stackframes that you may find useful. |
|
2526
|
|
|
|
|
|
|
|
|
2527
|
|
|
|
|
|
|
=back |
|
2528
|
|
|
|
|
|
|
|
|
2529
|
|
|
|
|
|
|
=head2 append_handler_package |
|
2530
|
|
|
|
|
|
|
|
|
2531
|
|
|
|
|
|
|
Usage: |
|
2532
|
|
|
|
|
|
|
<void> $cp->append_handler_package( $pkg <, $pkg2 ...>); |
|
2533
|
|
|
|
|
|
|
|
|
2534
|
|
|
|
|
|
|
The attribute L<handler_pkgs|/handler_pkgs> is an ArrayRef. |
|
2535
|
|
|
|
|
|
|
B<append_handler_package()> is sugar to make adding packages to the end of |
|
2536
|
|
|
|
|
|
|
L<handler_pkgs|/handler_pkgs> easier. |
|
2537
|
|
|
|
|
|
|
|
|
2538
|
|
|
|
|
|
|
=head2 append_section |
|
2539
|
|
|
|
|
|
|
|
|
2540
|
|
|
|
|
|
|
Usage: |
|
2541
|
|
|
|
|
|
|
<void> $cp->append_section( $array_ref <, $array_ref2...>); |
|
2542
|
|
|
|
|
|
|
|
|
2543
|
|
|
|
|
|
|
The L<sections|/sections> attribute is an ArrayRef containing |
|
2544
|
|
|
|
|
|
|
child ArrayRefs, one for each Section (like filled(), fixed() etc.). |
|
2545
|
|
|
|
|
|
|
B<append_section()> is sugar to make adding a Section request to the |
|
2546
|
|
|
|
|
|
|
L<sections|/sections> attribute, easier. Section requests are |
|
2547
|
|
|
|
|
|
|
added to the end of L<sections|/sections> (appended). |
|
2548
|
|
|
|
|
|
|
|
|
2549
|
|
|
|
|
|
|
=head2 banner |
|
2550
|
|
|
|
|
|
|
|
|
2551
|
|
|
|
|
|
|
Usage: |
|
2552
|
|
|
|
|
|
|
<String> $cp->banner(); |
|
2553
|
|
|
|
|
|
|
|
|
2554
|
|
|
|
|
|
|
B<banner()> produces the multi-line introduction to a diagnostic message. |
|
2555
|
|
|
|
|
|
|
The Banner is intended to stand out visually so it fills up the horizontal |
|
2556
|
|
|
|
|
|
|
space from left to right margins. The value of |
|
2557
|
|
|
|
|
|
|
L<columns|/columns> dictates the amount of fill needed. The |
|
2558
|
|
|
|
|
|
|
Banner looks something like this: |
|
2559
|
|
|
|
|
|
|
|
|
2560
|
|
|
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
2561
|
|
|
|
|
|
|
<banner_title> << <cleansed_handler> >> |
|
2562
|
|
|
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
2563
|
|
|
|
|
|
|
|
|
2564
|
|
|
|
|
|
|
In the above template, I<banner_title> is taken directly from the |
|
2565
|
|
|
|
|
|
|
L<banner_title|/banner_title> attribute. I<cleansed_handler> is |
|
2566
|
|
|
|
|
|
|
generated by invoking |
|
2567
|
|
|
|
|
|
|
L<identifier_presentation()|/identifier_presentation> on the |
|
2568
|
|
|
|
|
|
|
L<handler_name|/handler_name> attribute. |
|
2569
|
|
|
|
|
|
|
|
|
2570
|
|
|
|
|
|
|
=head2 call |
|
2571
|
|
|
|
|
|
|
|
|
2572
|
|
|
|
|
|
|
Usage: |
|
2573
|
|
|
|
|
|
|
<void> $cp->call( $handler, @optional_arguments ); |
|
2574
|
|
|
|
|
|
|
|
|
2575
|
|
|
|
|
|
|
The task of Handlers is to create Sections. Handlers can call other |
|
2576
|
|
|
|
|
|
|
Handlers to compose common Sections. |
|
2577
|
|
|
|
|
|
|
|
|
2578
|
|
|
|
|
|
|
Most Handlers know how to locate their peers because they reside in the |
|
2579
|
|
|
|
|
|
|
same package and have the same prefix conventions. B<call()> can |
|
2580
|
|
|
|
|
|
|
certainly be used to invoke peers, although it might seem like overkill. |
|
2581
|
|
|
|
|
|
|
|
|
2582
|
|
|
|
|
|
|
B<call()> is useful when Handlers reside in a hierarchy of packages and |
|
2583
|
|
|
|
|
|
|
you need a full search. B<call()> is also the only way to invoke |
|
2584
|
|
|
|
|
|
|
L<BUILTIN HANDLERS|/BUILTIN-HANDLERS:>. |
|
2585
|
|
|
|
|
|
|
|
|
2586
|
|
|
|
|
|
|
$cp->call( '*assertion_failure*', $description, \%status_vars ); |
|
2587
|
|
|
|
|
|
|
|
|
2588
|
|
|
|
|
|
|
B<call()> runs the algorithm described in L<HANDLER SEARCH|/HANDLER-SEARCH:>. |
|
2589
|
|
|
|
|
|
|
|
|
2590
|
|
|
|
|
|
|
=head2 contact_maintainer |
|
2591
|
|
|
|
|
|
|
|
|
2592
|
|
|
|
|
|
|
Usage: |
|
2593
|
|
|
|
|
|
|
<void> $cp->contact_maintainer(); |
|
2594
|
|
|
|
|
|
|
|
|
2595
|
|
|
|
|
|
|
If the L<maintainer|/maintainer> attribute is non-empty then a |
|
2596
|
|
|
|
|
|
|
Section containing the L<maintainer|/maintainer> string is |
|
2597
|
|
|
|
|
|
|
created. No Section is created if L<maintainer|/maintainer> is |
|
2598
|
|
|
|
|
|
|
empty. |
|
2599
|
|
|
|
|
|
|
|
|
2600
|
|
|
|
|
|
|
This works well if L<maintainer|/maintainer> contains contact |
|
2601
|
|
|
|
|
|
|
info. |
|
2602
|
|
|
|
|
|
|
|
|
2603
|
|
|
|
|
|
|
*** Please contact the maintainer *** |
|
2604
|
|
|
|
|
|
|
Your Name your.name@help.org (123)456-7890 |
|
2605
|
|
|
|
|
|
|
|
|
2606
|
|
|
|
|
|
|
=head2 decipher_child_error |
|
2607
|
|
|
|
|
|
|
|
|
2608
|
|
|
|
|
|
|
Usage: |
|
2609
|
|
|
|
|
|
|
<void> $cp->decipher_child_error(); |
|
2610
|
|
|
|
|
|
|
-or- |
|
2611
|
|
|
|
|
|
|
<void> $cp->decipher_child_error( $child_error ); |
|
2612
|
|
|
|
|
|
|
|
|
2613
|
|
|
|
|
|
|
Perl's B<$CHILD_ERROR> (B<$?>) encodes several bits of information about |
|
2614
|
|
|
|
|
|
|
how a child process terminates, see the B<perlvar> documentation on |
|
2615
|
|
|
|
|
|
|
B<$CHILD_ERROR> for details. B<decipher_child_error()> unpacks the |
|
2616
|
|
|
|
|
|
|
various bits of information in B<$CHILD_ERROR> and converts them into a |
|
2617
|
|
|
|
|
|
|
L<filled()|/filled> Section. Examples: |
|
2618
|
|
|
|
|
|
|
|
|
2619
|
|
|
|
|
|
|
*** Process Succeeded *** |
|
2620
|
|
|
|
|
|
|
The child process completed normally (exit code 0). |
|
2621
|
|
|
|
|
|
|
|
|
2622
|
|
|
|
|
|
|
*** Process returns failing status *** |
|
2623
|
|
|
|
|
|
|
The child process terminated with an exit code of 14. |
|
2624
|
|
|
|
|
|
|
|
|
2625
|
|
|
|
|
|
|
*** Process terminated by signal *** |
|
2626
|
|
|
|
|
|
|
The child process was terminated by SIGSEGV (signal 11). |
|
2627
|
|
|
|
|
|
|
|
|
2628
|
|
|
|
|
|
|
If a I<$child_error> argument is provided then the argument value is |
|
2629
|
|
|
|
|
|
|
deciphered, otherwise the value held in the L<child_error|/child_error> |
|
2630
|
|
|
|
|
|
|
attribute is used. |
|
2631
|
|
|
|
|
|
|
|
|
2632
|
|
|
|
|
|
|
=head2 directory |
|
2633
|
|
|
|
|
|
|
|
|
2634
|
|
|
|
|
|
|
Usage: |
|
2635
|
|
|
|
|
|
|
<void> $cp->directory( $dir <, $title >); |
|
2636
|
|
|
|
|
|
|
|
|
2637
|
|
|
|
|
|
|
The B<directory()> method creates a L<fixed()|/fixed> Section. The |
|
2638
|
|
|
|
|
|
|
optional I<$title>, if supplied, forms the title for the Section, |
|
2639
|
|
|
|
|
|
|
otherwise C<'Directory'> is used as the title. |
|
2640
|
|
|
|
|
|
|
|
|
2641
|
|
|
|
|
|
|
Output from B<Cwd::abs_path()> is used to form the body of the Section. |
|
2642
|
|
|
|
|
|
|
|
|
2643
|
|
|
|
|
|
|
=head2 errno_section |
|
2644
|
|
|
|
|
|
|
|
|
2645
|
|
|
|
|
|
|
Usage: |
|
2646
|
|
|
|
|
|
|
<void> $cp->errno_section( <$title> ); |
|
2647
|
|
|
|
|
|
|
|
|
2648
|
|
|
|
|
|
|
A filled Section is created using the contents of the |
|
2649
|
|
|
|
|
|
|
L<string_errno|/string_errno> attribute. If I<$title> is |
|
2650
|
|
|
|
|
|
|
not provided then 'System Diagnostic' is used as the Header title. |
|
2651
|
|
|
|
|
|
|
|
|
2652
|
|
|
|
|
|
|
No Section is created if the L<string_errno|/string_errno> |
|
2653
|
|
|
|
|
|
|
attribute is empty. |
|
2654
|
|
|
|
|
|
|
|
|
2655
|
|
|
|
|
|
|
=head2 filename |
|
2656
|
|
|
|
|
|
|
|
|
2657
|
|
|
|
|
|
|
Usage: |
|
2658
|
|
|
|
|
|
|
<void> $cp->filename( $file <, $title >); |
|
2659
|
|
|
|
|
|
|
|
|
2660
|
|
|
|
|
|
|
The B<filename()> method creates a L<fixed()|/fixed> Section. The |
|
2661
|
|
|
|
|
|
|
optional I<$title>, if supplied, forms the title for the Section, |
|
2662
|
|
|
|
|
|
|
otherwise C<'Filename'> is used as the title. |
|
2663
|
|
|
|
|
|
|
|
|
2664
|
|
|
|
|
|
|
Output from B<Cwd::abs_path()> is used to form the body of the Section. |
|
2665
|
|
|
|
|
|
|
|
|
2666
|
|
|
|
|
|
|
=head2 filled |
|
2667
|
|
|
|
|
|
|
|
|
2668
|
|
|
|
|
|
|
Usage: |
|
2669
|
|
|
|
|
|
|
<void> $cp->filled( $content <, $title >); |
|
2670
|
|
|
|
|
|
|
|
|
2671
|
|
|
|
|
|
|
B<filled()> creates a Section. The Section is introduced with a |
|
2672
|
|
|
|
|
|
|
L<header()|/header> containing I<$title>. The body of the Section is |
|
2673
|
|
|
|
|
|
|
produced by reformatting I<$content> into paragraphs of length-limited |
|
2674
|
|
|
|
|
|
|
lines. |
|
2675
|
|
|
|
|
|
|
|
|
2676
|
|
|
|
|
|
|
If I<$title> is not supplied, or if it is undef, then the |
|
2677
|
|
|
|
|
|
|
L<section_title|/section_title> attribute is used in its place. If |
|
2678
|
|
|
|
|
|
|
I<$title> is an empty string then no Header is produced. This makes it |
|
2679
|
|
|
|
|
|
|
easy to chain together Fixed and Filled Sections under the same Header. |
|
2680
|
|
|
|
|
|
|
|
|
2681
|
|
|
|
|
|
|
Any spaces at the beginning of each paragraph in I<$content> sets the |
|
2682
|
|
|
|
|
|
|
relative indentation for the whole paragraph. Each paragraph may have |
|
2683
|
|
|
|
|
|
|
different indentations. |
|
2684
|
|
|
|
|
|
|
|
|
2685
|
|
|
|
|
|
|
Paragraphs are reformatted by splitting them into words, on whitespace, then |
|
2686
|
|
|
|
|
|
|
building up new lines. Each line starts with spaces corresponding to the |
|
2687
|
|
|
|
|
|
|
sum of L<header_indent|/header_indent>, L<body_indent|/body_indent> and any |
|
2688
|
|
|
|
|
|
|
paragraph-specific indentation. Lines are then filled with words to achieve |
|
2689
|
|
|
|
|
|
|
a target line width. The target width is given by the L<columns|/columns> |
|
2690
|
|
|
|
|
|
|
attribute. |
|
2691
|
|
|
|
|
|
|
|
|
2692
|
|
|
|
|
|
|
In actuality, all the B<filled()> method does is to add a request for a |
|
2693
|
|
|
|
|
|
|
"filled_section" onto the end of the B<sections> list. The actual |
|
2694
|
|
|
|
|
|
|
processing is performed by L<filled_section()|/filled_section> when |
|
2695
|
|
|
|
|
|
|
L<render_message()|/render_message> traverses the B<sections> list. |
|
2696
|
|
|
|
|
|
|
What this means is that the settings for attributes like |
|
2697
|
|
|
|
|
|
|
L<section_title|/section_title>, L<columns|/columns>, |
|
2698
|
|
|
|
|
|
|
L<header_indent|/header_indent> and |
|
2699
|
|
|
|
|
|
|
L<body_indent|/body_indent> only come into play when |
|
2700
|
|
|
|
|
|
|
L<render_message()|/render_message> is run. |
|
2701
|
|
|
|
|
|
|
|
|
2702
|
|
|
|
|
|
|
See L<filled_section()|/filled_section> for details. |
|
2703
|
|
|
|
|
|
|
|
|
2704
|
|
|
|
|
|
|
=head2 filled_section |
|
2705
|
|
|
|
|
|
|
|
|
2706
|
|
|
|
|
|
|
Usage: |
|
2707
|
|
|
|
|
|
|
<String> $cp->filled_section( $content, $title ); |
|
2708
|
|
|
|
|
|
|
|
|
2709
|
|
|
|
|
|
|
B<filled_section()> is not usually invoked directly by users. |
|
2710
|
|
|
|
|
|
|
L<render_message()|/render_message> invokes B<filled_section()> as it |
|
2711
|
|
|
|
|
|
|
traverses the list held in the L<sections|/sections> attribute. |
|
2712
|
|
|
|
|
|
|
|
|
2713
|
|
|
|
|
|
|
I<$content> is expected to be a string. If I<$content> is an empty string |
|
2714
|
|
|
|
|
|
|
then no Section is produced - an empty string is returned. |
|
2715
|
|
|
|
|
|
|
|
|
2716
|
|
|
|
|
|
|
I<$title> is converted into a section-title using L<header()|/header>. |
|
2717
|
|
|
|
|
|
|
|
|
2718
|
|
|
|
|
|
|
I<$content> is split into paragraphs wherever there are two or more |
|
2719
|
|
|
|
|
|
|
consecutive newlines, more specifically using this regex: |
|
2720
|
|
|
|
|
|
|
|
|
2721
|
|
|
|
|
|
|
/(?: \r? \n ){2,}/x |
|
2722
|
|
|
|
|
|
|
|
|
2723
|
|
|
|
|
|
|
Each paragraph is examined for leading whitespace. This leading whitespace |
|
2724
|
|
|
|
|
|
|
is processed by converting tabs into spaces on eight-column boundarys. The |
|
2725
|
|
|
|
|
|
|
converted whitespace forms the supplemental indentation for the paragraph. |
|
2726
|
|
|
|
|
|
|
|
|
2727
|
|
|
|
|
|
|
New paragraphs are formed a line at a time by starting with an indentation |
|
2728
|
|
|
|
|
|
|
amount corresponding to the sum of L<header_indent|/header_indent>, |
|
2729
|
|
|
|
|
|
|
L<body_indent|/body_indent> and any supplemental indentation. Words from |
|
2730
|
|
|
|
|
|
|
the old paragraph are added to the line so long as the line length does not |
|
2731
|
|
|
|
|
|
|
exceed L<columns|/columns>. At least one word is always added, even if |
|
2732
|
|
|
|
|
|
|
L<columns|/columns> is exceeded. |
|
2733
|
|
|
|
|
|
|
|
|
2734
|
|
|
|
|
|
|
Any trailing whitespace is removed. Output paragraphs are joined with a |
|
2735
|
|
|
|
|
|
|
blank line. The returned string is the concatenation of the section title, |
|
2736
|
|
|
|
|
|
|
the paragraphs and a trailing blank line. |
|
2737
|
|
|
|
|
|
|
|
|
2738
|
|
|
|
|
|
|
Override B<filled_section()> in a sub-class, rather than |
|
2739
|
|
|
|
|
|
|
L<filled()|/filled>, if you want different filling behavior. |
|
2740
|
|
|
|
|
|
|
|
|
2741
|
|
|
|
|
|
|
=head2 fixed |
|
2742
|
|
|
|
|
|
|
|
|
2743
|
|
|
|
|
|
|
Usage: |
|
2744
|
|
|
|
|
|
|
<void> $cp->fixed( $content <, $title >); |
|
2745
|
|
|
|
|
|
|
|
|
2746
|
|
|
|
|
|
|
B<fixed()> creates a Section. The Section is introduced with a |
|
2747
|
|
|
|
|
|
|
L<header()|/header> containing I<$title>. The body of the Section is formed |
|
2748
|
|
|
|
|
|
|
by retaining the formatting already present in I<$content>. |
|
2749
|
|
|
|
|
|
|
|
|
2750
|
|
|
|
|
|
|
If I<$title> is not supplied, or if it is undef, then the |
|
2751
|
|
|
|
|
|
|
L<section_title|/section_title> attribute is used in its place. If |
|
2752
|
|
|
|
|
|
|
I<$title> is an empty string then no Header is included. This makes it easy |
|
2753
|
|
|
|
|
|
|
to chain together Fixed and Filled Sections under the same Header. |
|
2754
|
|
|
|
|
|
|
|
|
2755
|
|
|
|
|
|
|
Each line in I<$content> is indented by a constant amount corresponding to |
|
2756
|
|
|
|
|
|
|
the L<header_indent|/header_indent> plus the L<body_indent|/body_indent>. |
|
2757
|
|
|
|
|
|
|
Tabs in I<$content> are folded into spaces to preserve column alignment |
|
2758
|
|
|
|
|
|
|
before the indentation is prepended. Trailing whitespace on each line is |
|
2759
|
|
|
|
|
|
|
replaced with an appropriate line terminator for the platform. I<$content> |
|
2760
|
|
|
|
|
|
|
is otherwise unmolested. Almost WYSIWYG. |
|
2761
|
|
|
|
|
|
|
|
|
2762
|
|
|
|
|
|
|
In actuality, all the B<fixed()> method does is to add a request for a |
|
2763
|
|
|
|
|
|
|
"fixed_section" onto the end of the B<sections> list. The actual processing |
|
2764
|
|
|
|
|
|
|
is performed by the L<fixed_section()|/fixed_section> method when the |
|
2765
|
|
|
|
|
|
|
L<render_message()|/render_message> method traverses the B<sections> list. |
|
2766
|
|
|
|
|
|
|
What this means is that the settings for attributes like |
|
2767
|
|
|
|
|
|
|
L<section_title|/section_title>, L<header_indent|/header_indent> and |
|
2768
|
|
|
|
|
|
|
L<body_indent|/body_indent> only matter at the time |
|
2769
|
|
|
|
|
|
|
L<render_message()|/render_message> is run. |
|
2770
|
|
|
|
|
|
|
|
|
2771
|
|
|
|
|
|
|
See L<fixed_section()|/fixed_section> for details. |
|
2772
|
|
|
|
|
|
|
|
|
2773
|
|
|
|
|
|
|
=head2 fixed_section |
|
2774
|
|
|
|
|
|
|
|
|
2775
|
|
|
|
|
|
|
Usage: |
|
2776
|
|
|
|
|
|
|
<String> $cp->fixed_section( $content, $title ); |
|
2777
|
|
|
|
|
|
|
|
|
2778
|
|
|
|
|
|
|
B<fixed_section()> is not usually invoked directly by users. |
|
2779
|
|
|
|
|
|
|
L<render_message()|/render_message> invokes B<fixed_section()> as |
|
2780
|
|
|
|
|
|
|
it traverses the list in the L<sections|/sections> attribute. |
|
2781
|
|
|
|
|
|
|
|
|
2782
|
|
|
|
|
|
|
I<$content> is expected to be a string. If I<$content> is the empty |
|
2783
|
|
|
|
|
|
|
string then no Section is generated and an empty string is returned. |
|
2784
|
|
|
|
|
|
|
|
|
2785
|
|
|
|
|
|
|
I<$title> is converted into a Section title string using |
|
2786
|
|
|
|
|
|
|
L<header()|/header>. |
|
2787
|
|
|
|
|
|
|
|
|
2788
|
|
|
|
|
|
|
I<$content> is split into lines on newline ("\n") characters for |
|
2789
|
|
|
|
|
|
|
processing. Trailing whitespace is removed. Embedded tabs are converted |
|
2790
|
|
|
|
|
|
|
to the equivalent number of spaces assuming eight character boundarys. |
|
2791
|
|
|
|
|
|
|
Indentation corresponding to the sum of |
|
2792
|
|
|
|
|
|
|
L<header_indent|/header_indent> and |
|
2793
|
|
|
|
|
|
|
L<body_indent|/body_indent> is added to the beginning of each |
|
2794
|
|
|
|
|
|
|
line. Lines are joined with platform-appropriate line termination. |
|
2795
|
|
|
|
|
|
|
|
|
2796
|
|
|
|
|
|
|
Trailing whitespace is removed, the section-title is prepended and a |
|
2797
|
|
|
|
|
|
|
single blank line is added to the end. |
|
2798
|
|
|
|
|
|
|
|
|
2799
|
|
|
|
|
|
|
=head2 header |
|
2800
|
|
|
|
|
|
|
|
|
2801
|
|
|
|
|
|
|
Usage: |
|
2802
|
|
|
|
|
|
|
<String> $cp->header( $title ); |
|
2803
|
|
|
|
|
|
|
|
|
2804
|
|
|
|
|
|
|
B<header()> produces an introductory line for a Section of paragraphs. |
|
2805
|
|
|
|
|
|
|
The line is indented from the left margin by |
|
2806
|
|
|
|
|
|
|
L<header_indent|/header_indent> spaces. The line is formed |
|
2807
|
|
|
|
|
|
|
using the following template: |
|
2808
|
|
|
|
|
|
|
|
|
2809
|
|
|
|
|
|
|
<indent>*** <$title> *** |
|
2810
|
|
|
|
|
|
|
|
|
2811
|
|
|
|
|
|
|
The intent is to provide an introductory heading for Section paragraphs. |
|
2812
|
|
|
|
|
|
|
|
|
2813
|
|
|
|
|
|
|
*** Description *** |
|
2814
|
|
|
|
|
|
|
The database server is refusing connections. |
|
2815
|
|
|
|
|
|
|
|
|
2816
|
|
|
|
|
|
|
If I<$title> is undef then the L<section_title|/section_title> |
|
2817
|
|
|
|
|
|
|
attribute is used in its place. Passing an empty string (C<''>) for |
|
2818
|
|
|
|
|
|
|
I<title> causes B<header()> to omit Header generation. In this case an |
|
2819
|
|
|
|
|
|
|
empty string is returned. |
|
2820
|
|
|
|
|
|
|
|
|
2821
|
|
|
|
|
|
|
B<header()> is called by the Section creating methods |
|
2822
|
|
|
|
|
|
|
L<filled_section()|/filled_section> and |
|
2823
|
|
|
|
|
|
|
L<fixed_section()|/fixed_section>. |
|
2824
|
|
|
|
|
|
|
|
|
2825
|
|
|
|
|
|
|
Subclass B<Carp::Proxy> and override B<header()> for a different look. |
|
2826
|
|
|
|
|
|
|
|
|
2827
|
|
|
|
|
|
|
=head2 identifier_presentation |
|
2828
|
|
|
|
|
|
|
|
|
2829
|
|
|
|
|
|
|
Usage: |
|
2830
|
|
|
|
|
|
|
<String> $class->identifier_presentation( $name ); |
|
2831
|
|
|
|
|
|
|
|
|
2832
|
|
|
|
|
|
|
The Banner reads better when words in the |
|
2833
|
|
|
|
|
|
|
L<handler_name|/handler_name> are separated by spaces rather |
|
2834
|
|
|
|
|
|
|
than underscores (C<_>). Likewise with camelCasedIdentifiers. |
|
2835
|
|
|
|
|
|
|
|
|
2836
|
|
|
|
|
|
|
Underscores are replaced by single spaces everywhere they occur. Spaces |
|
2837
|
|
|
|
|
|
|
are inserted everywhere character-case changes from lower to upper, and |
|
2838
|
|
|
|
|
|
|
upper-case characters are folded to lower-case. The following are example |
|
2839
|
|
|
|
|
|
|
conversions: |
|
2840
|
|
|
|
|
|
|
|
|
2841
|
|
|
|
|
|
|
'no_user_credentials' => 'no user credentials' |
|
2842
|
|
|
|
|
|
|
'nonexistentRecord' => 'nonexistent record' |
|
2843
|
|
|
|
|
|
|
|
|
2844
|
|
|
|
|
|
|
Sub-class B<Carp::Proxy> and override B<identifier_presentation()> if |
|
2845
|
|
|
|
|
|
|
you want a different convention. |
|
2846
|
|
|
|
|
|
|
|
|
2847
|
|
|
|
|
|
|
=head2 import |
|
2848
|
|
|
|
|
|
|
|
|
2849
|
|
|
|
|
|
|
Usage: |
|
2850
|
|
|
|
|
|
|
<void> $class->import( <%attrs_by_proxy>); |
|
2851
|
|
|
|
|
|
|
|
|
2852
|
|
|
|
|
|
|
B<import()> accepts specifications for Proxy construction. Specifications |
|
2853
|
|
|
|
|
|
|
take the form of a proxyname and a hashref of attribute initializations. |
|
2854
|
|
|
|
|
|
|
|
|
2855
|
|
|
|
|
|
|
proxyname1 => { |
|
2856
|
|
|
|
|
|
|
attributeA => initial_valueA, |
|
2857
|
|
|
|
|
|
|
attributeB => initial_valueB, |
|
2858
|
|
|
|
|
|
|
... |
|
2859
|
|
|
|
|
|
|
} |
|
2860
|
|
|
|
|
|
|
|
|
2861
|
|
|
|
|
|
|
Any number of proxyname, hashref pairs may be specified; a proxy subroutine |
|
2862
|
|
|
|
|
|
|
will be constructed for each pair. |
|
2863
|
|
|
|
|
|
|
|
|
2864
|
|
|
|
|
|
|
If there is only one argument it is taken to be a proxyname introducing an |
|
2865
|
|
|
|
|
|
|
empty hashref. If there are no arguments then it is assumed that the |
|
2866
|
|
|
|
|
|
|
builder-specified default for the L<proxy_name|/proxy_name> attribute |
|
2867
|
|
|
|
|
|
|
(C<'fatal'>), should be used for the proxyname and an empty hashref used for |
|
2868
|
|
|
|
|
|
|
the attribute initializations. |
|
2869
|
|
|
|
|
|
|
|
|
2870
|
|
|
|
|
|
|
B<import()> probes the callstack to determine the package and filename of |
|
2871
|
|
|
|
|
|
|
the user code that called B<import()>. B<import()> uses these values to create |
|
2872
|
|
|
|
|
|
|
a hash containing the attributes L<proxy_filename|/proxy_filename>, |
|
2873
|
|
|
|
|
|
|
L<proxy_name|/proxy_name> L<proxy_package|/proxy_package> and |
|
2874
|
|
|
|
|
|
|
L<fq_proxy_name|/fq_proxy_name>. Any supplied attributes are added to the |
|
2875
|
|
|
|
|
|
|
hash. The builtin handler L<*configuration*|/configuration> returns a |
|
2876
|
|
|
|
|
|
|
reference to this hash. |
|
2877
|
|
|
|
|
|
|
|
|
2878
|
|
|
|
|
|
|
=head2 list_handler_packages |
|
2879
|
|
|
|
|
|
|
|
|
2880
|
|
|
|
|
|
|
Usage: |
|
2881
|
|
|
|
|
|
|
<list> $cp->list_handler_packages(); |
|
2882
|
|
|
|
|
|
|
|
|
2883
|
|
|
|
|
|
|
B<list_handler_packages()> is sugar that dereferences the |
|
2884
|
|
|
|
|
|
|
L<handler_pkgs|/handler_pkgs> attribute (an ArrayRef) and |
|
2885
|
|
|
|
|
|
|
returns the contents. |
|
2886
|
|
|
|
|
|
|
|
|
2887
|
|
|
|
|
|
|
=head2 list_sections |
|
2888
|
|
|
|
|
|
|
|
|
2889
|
|
|
|
|
|
|
Usage: |
|
2890
|
|
|
|
|
|
|
<list> $cp->list_sections(); |
|
2891
|
|
|
|
|
|
|
|
|
2892
|
|
|
|
|
|
|
The L<sections|/sections> attribute is an ArrayRef. |
|
2893
|
|
|
|
|
|
|
B<list_sections()> is sugar to return all the elements of |
|
2894
|
|
|
|
|
|
|
L<sections|/sections>. |
|
2895
|
|
|
|
|
|
|
|
|
2896
|
|
|
|
|
|
|
=head2 new |
|
2897
|
|
|
|
|
|
|
|
|
2898
|
|
|
|
|
|
|
Usage: |
|
2899
|
|
|
|
|
|
|
<Carp::Proxy object> $class->new |
|
2900
|
|
|
|
|
|
|
( arg => harvested $_, |
|
2901
|
|
|
|
|
|
|
eval_error => harvested $@, |
|
2902
|
|
|
|
|
|
|
fq_proxy_name => 'package::subname', |
|
2903
|
|
|
|
|
|
|
handler_name => 'name of handler', |
|
2904
|
|
|
|
|
|
|
numeric_errno => harvested 0 + $!, |
|
2905
|
|
|
|
|
|
|
proxy_filename => 'filename', |
|
2906
|
|
|
|
|
|
|
proxy_name => 'subname', |
|
2907
|
|
|
|
|
|
|
proxy_package => 'package', |
|
2908
|
|
|
|
|
|
|
string_errno => harvested '' . $!, |
|
2909
|
|
|
|
|
|
|
< attribute => value ...> |
|
2910
|
|
|
|
|
|
|
); |
|
2911
|
|
|
|
|
|
|
|
|
2912
|
|
|
|
|
|
|
I<new()> is normally called by the Proxy, so this documentation is only |
|
2913
|
|
|
|
|
|
|
useful if you are using the object for your own purposes. There are a large |
|
2914
|
|
|
|
|
|
|
number of required attribute-value pairs. Specification for any additional |
|
2915
|
|
|
|
|
|
|
attributes is supported. Builder methods are invoked for all unspecified |
|
2916
|
|
|
|
|
|
|
attributes. |
|
2917
|
|
|
|
|
|
|
|
|
2918
|
|
|
|
|
|
|
There is some inconsistency around the L<proxy_name|/proxy_name> attribute. |
|
2919
|
|
|
|
|
|
|
The L<proxy_name|/proxy_name> is required by I<new()> even though it has a |
|
2920
|
|
|
|
|
|
|
builder method. The builder is for use by L<import()|/import>, which |
|
2921
|
|
|
|
|
|
|
invokes it if needed, and passes the result to new(). |
|
2922
|
|
|
|
|
|
|
|
|
2923
|
|
|
|
|
|
|
=head2 perform_disposition |
|
2924
|
|
|
|
|
|
|
|
|
2925
|
|
|
|
|
|
|
Usage: |
|
2926
|
|
|
|
|
|
|
<Scalar> $cp->perform_disposition(); |
|
2927
|
|
|
|
|
|
|
|
|
2928
|
|
|
|
|
|
|
The L<disposition|/disposition> attribute determines the final |
|
2929
|
|
|
|
|
|
|
actions of the Proxy, which are carried out by B<perform_disposition()>. |
|
2930
|
|
|
|
|
|
|
Valid settings for L<disposition|/disposition> are: |
|
2931
|
|
|
|
|
|
|
|
|
2932
|
|
|
|
|
|
|
=over 4 |
|
2933
|
|
|
|
|
|
|
|
|
2934
|
|
|
|
|
|
|
=item B<'warn'> |
|
2935
|
|
|
|
|
|
|
|
|
2936
|
|
|
|
|
|
|
A I<disposition> of C<'warn'> causes B<perform_disposition()> to do this: |
|
2937
|
|
|
|
|
|
|
|
|
2938
|
|
|
|
|
|
|
warn $cp; |
|
2939
|
|
|
|
|
|
|
return (); |
|
2940
|
|
|
|
|
|
|
|
|
2941
|
|
|
|
|
|
|
=item B<'die'> |
|
2942
|
|
|
|
|
|
|
|
|
2943
|
|
|
|
|
|
|
A I<disposition> of C<'die'> causes B<perform_disposition()> to do this: |
|
2944
|
|
|
|
|
|
|
|
|
2945
|
|
|
|
|
|
|
$ERRNO = $cp->exit_code; |
|
2946
|
|
|
|
|
|
|
die $cp; |
|
2947
|
|
|
|
|
|
|
|
|
2948
|
|
|
|
|
|
|
See Perl's B<die()> for an explanation of propagating $ERRNO into the exit |
|
2949
|
|
|
|
|
|
|
code for the process. |
|
2950
|
|
|
|
|
|
|
|
|
2951
|
|
|
|
|
|
|
C<'die'> is the default I<disposition>. |
|
2952
|
|
|
|
|
|
|
|
|
2953
|
|
|
|
|
|
|
=item B<'return'> |
|
2954
|
|
|
|
|
|
|
|
|
2955
|
|
|
|
|
|
|
The I<disposition> of C<'return'> is unusual; it signifies a desire to |
|
2956
|
|
|
|
|
|
|
abort the whole death-by-proxy process. B<perform_disposition> does this: |
|
2957
|
|
|
|
|
|
|
|
|
2958
|
|
|
|
|
|
|
return $cp; |
|
2959
|
|
|
|
|
|
|
|
|
2960
|
|
|
|
|
|
|
=item B<CodeRef> |
|
2961
|
|
|
|
|
|
|
|
|
2962
|
|
|
|
|
|
|
The user can take control of disposition by supplying a CodeRef for |
|
2963
|
|
|
|
|
|
|
I<disposition>. In this case, the behavior of B<perform_disposition()> |
|
2964
|
|
|
|
|
|
|
is: |
|
2965
|
|
|
|
|
|
|
|
|
2966
|
|
|
|
|
|
|
return $cp->disposition->( $cp ); |
|
2967
|
|
|
|
|
|
|
|
|
2968
|
|
|
|
|
|
|
=back |
|
2969
|
|
|
|
|
|
|
|
|
2970
|
|
|
|
|
|
|
=head2 prepend_handler_package |
|
2971
|
|
|
|
|
|
|
|
|
2972
|
|
|
|
|
|
|
Usage: |
|
2973
|
|
|
|
|
|
|
<void> $cp->prepend_handler_package( $pkg <, $pkg2...>); |
|
2974
|
|
|
|
|
|
|
|
|
2975
|
|
|
|
|
|
|
The attribute L<handler_pkgs|/handler_pkgs> is an ArrayRef. |
|
2976
|
|
|
|
|
|
|
B<prepend_handler_package()> is sugar to make adding packages to the front |
|
2977
|
|
|
|
|
|
|
of L<handler_pkgs|/handler_pkgs> easier. |
|
2978
|
|
|
|
|
|
|
|
|
2979
|
|
|
|
|
|
|
=head2 prepend_section |
|
2980
|
|
|
|
|
|
|
|
|
2981
|
|
|
|
|
|
|
Usage: |
|
2982
|
|
|
|
|
|
|
<void> $cp->prepend_section( $array_ref <, $array_ref2...>); |
|
2983
|
|
|
|
|
|
|
|
|
2984
|
|
|
|
|
|
|
The L<sections|/sections> attribute is an ArrayRef containing |
|
2985
|
|
|
|
|
|
|
child ArrayRefs, one for each Section (like filled(), fixed() etc.). |
|
2986
|
|
|
|
|
|
|
B<prepend_section()> is sugar to make adding a Section request to the |
|
2987
|
|
|
|
|
|
|
L<sections|/sections> attribute, easier. Section requests are |
|
2988
|
|
|
|
|
|
|
added to the front of L<sections|/sections> (prepended). |
|
2989
|
|
|
|
|
|
|
|
|
2990
|
|
|
|
|
|
|
=head2 raw |
|
2991
|
|
|
|
|
|
|
|
|
2992
|
|
|
|
|
|
|
Usage: |
|
2993
|
|
|
|
|
|
|
<void> $cp->raw( $content ); |
|
2994
|
|
|
|
|
|
|
|
|
2995
|
|
|
|
|
|
|
B<raw()> provides an alternative to L<fixed()|/fixed> and |
|
2996
|
|
|
|
|
|
|
L<filled()|/filled> for composing diagnostic Sections. |
|
2997
|
|
|
|
|
|
|
|
|
2998
|
|
|
|
|
|
|
In effect, B<raw()> creates a Section containing only B<$content>. |
|
2999
|
|
|
|
|
|
|
You are completely responsible for the final appearance of the Section; |
|
3000
|
|
|
|
|
|
|
there is no Header, no trailing blank line, no indentation and no |
|
3001
|
|
|
|
|
|
|
platform appropriate line termination. |
|
3002
|
|
|
|
|
|
|
|
|
3003
|
|
|
|
|
|
|
In actuality, all the B<raw()> method does is to add a request for a raw |
|
3004
|
|
|
|
|
|
|
Section onto the B<sections> list; the actual processing is performed by |
|
3005
|
|
|
|
|
|
|
the L<raw_section()|/raw_section> method when the |
|
3006
|
|
|
|
|
|
|
L<render_message()|/render_message> traverses B<sections>. |
|
3007
|
|
|
|
|
|
|
|
|
3008
|
|
|
|
|
|
|
See L<raw_section()|/raw_section> for details. |
|
3009
|
|
|
|
|
|
|
|
|
3010
|
|
|
|
|
|
|
=head2 raw_section |
|
3011
|
|
|
|
|
|
|
|
|
3012
|
|
|
|
|
|
|
Usage: |
|
3013
|
|
|
|
|
|
|
<String> $cp->raw_section( $content ); |
|
3014
|
|
|
|
|
|
|
|
|
3015
|
|
|
|
|
|
|
B<raw_section()> is not usually invoked directly by users. |
|
3016
|
|
|
|
|
|
|
L<render_message()|/render_message> invokes B<raw_section()> as it |
|
3017
|
|
|
|
|
|
|
traverses the list in the L<sections|/sections> attribute. |
|
3018
|
|
|
|
|
|
|
|
|
3019
|
|
|
|
|
|
|
B<raw_section()> does nothing; the returned string is simply a copy of |
|
3020
|
|
|
|
|
|
|
I<$content>. |
|
3021
|
|
|
|
|
|
|
|
|
3022
|
|
|
|
|
|
|
=head2 render_message |
|
3023
|
|
|
|
|
|
|
|
|
3024
|
|
|
|
|
|
|
Usage: |
|
3025
|
|
|
|
|
|
|
<String> $cp->render_message(); |
|
3026
|
|
|
|
|
|
|
|
|
3027
|
|
|
|
|
|
|
The behavior of B<render_message()> is dependent on the setting of the |
|
3028
|
|
|
|
|
|
|
attribute L<as_yaml|/as_yaml>. If L<as_yaml|/as_yaml> is False, which is |
|
3029
|
|
|
|
|
|
|
the default, then B<render_message()> walks the list of |
|
3030
|
|
|
|
|
|
|
section-specifications stored in the L<sections|/sections> attribute, |
|
3031
|
|
|
|
|
|
|
executing each one in turn. The return value is formed by concatenating |
|
3032
|
|
|
|
|
|
|
each of the results. |
|
3033
|
|
|
|
|
|
|
|
|
3034
|
|
|
|
|
|
|
The L<sections|/sections> attribute, an ArrayRef, is expected to contain any |
|
3035
|
|
|
|
|
|
|
number of ArrayRef elements. Each child ArrayRef must have at least one |
|
3036
|
|
|
|
|
|
|
element: the name of a method to be invoked. Any remaining elements are |
|
3037
|
|
|
|
|
|
|
passed to the invoked method as arguments. For example, a |
|
3038
|
|
|
|
|
|
|
L<sections|/sections> specification that looks like this: |
|
3039
|
|
|
|
|
|
|
|
|
3040
|
|
|
|
|
|
|
[ |
|
3041
|
|
|
|
|
|
|
[ 'filled_section', 'content1', 'title1' ], |
|
3042
|
|
|
|
|
|
|
[ 'filled_section', 'content2', 'title2' ], |
|
3043
|
|
|
|
|
|
|
] |
|
3044
|
|
|
|
|
|
|
|
|
3045
|
|
|
|
|
|
|
Results in the execution of something like this: |
|
3046
|
|
|
|
|
|
|
|
|
3047
|
|
|
|
|
|
|
my $buffer = $cp->banner(); |
|
3048
|
|
|
|
|
|
|
|
|
3049
|
|
|
|
|
|
|
$buffer .= $cp->filled_section( 'content1', 'title1' ); |
|
3050
|
|
|
|
|
|
|
$buffer .= $cp->filled_section( 'content2', 'title2' ); |
|
3051
|
|
|
|
|
|
|
|
|
3052
|
|
|
|
|
|
|
return $buffer; |
|
3053
|
|
|
|
|
|
|
|
|
3054
|
|
|
|
|
|
|
The L<sections|/sections> list is unchanged by the traversal, so |
|
3055
|
|
|
|
|
|
|
B<render_message()> may be invoked repeatedly. Settings for attributes like |
|
3056
|
|
|
|
|
|
|
L<banner_title|/banner_title>, L<columns|/columns>, |
|
3057
|
|
|
|
|
|
|
L<section_title|/section_title>, L<header_indent|/header_indent> and |
|
3058
|
|
|
|
|
|
|
L<body_indent|/body_indent> can be changed between invocations to vary the |
|
3059
|
|
|
|
|
|
|
message format. |
|
3060
|
|
|
|
|
|
|
|
|
3061
|
|
|
|
|
|
|
Changing attributes like L<context|/context>, which are |
|
3062
|
|
|
|
|
|
|
referenced during the generation of Section specifications, have no effect. |
|
3063
|
|
|
|
|
|
|
|
|
3064
|
|
|
|
|
|
|
If L<as_yaml|/as_yaml> is True then we return a string that |
|
3065
|
|
|
|
|
|
|
is a YAML dump of the B<Carp::Proxy> object, something like this: |
|
3066
|
|
|
|
|
|
|
|
|
3067
|
|
|
|
|
|
|
return YAML::XS::Dump( $cp ); |
|
3068
|
|
|
|
|
|
|
|
|
3069
|
|
|
|
|
|
|
The intent here is to use YAML to serialize all aspects of the |
|
3070
|
|
|
|
|
|
|
B<Carp::Proxy> object. Assuming that we have a |
|
3071
|
|
|
|
|
|
|
L<disposition|/disposition> setting of B<die>, our |
|
3072
|
|
|
|
|
|
|
serialized object will be written out to STDERR, where it can be captured |
|
3073
|
|
|
|
|
|
|
by a parent process and reconstituted. The reconstituted object can |
|
3074
|
|
|
|
|
|
|
be examined, or augmented with parental context and rethrown. |
|
3075
|
|
|
|
|
|
|
|
|
3076
|
|
|
|
|
|
|
=head2 synopsis |
|
3077
|
|
|
|
|
|
|
|
|
3078
|
|
|
|
|
|
|
Usage: |
|
3079
|
|
|
|
|
|
|
<void> $cp->synopsis( %optional_supplements ); |
|
3080
|
|
|
|
|
|
|
|
|
3081
|
|
|
|
|
|
|
The B<synopsis()> method employs B<Pod::Usage::pod2usage()> to create a |
|
3082
|
|
|
|
|
|
|
Section from the user's POD. User POD is located by searching in the |
|
3083
|
|
|
|
|
|
|
L<pod_filename|/pod_filename> attribute. |
|
3084
|
|
|
|
|
|
|
|
|
3085
|
|
|
|
|
|
|
The call to B<pod2usage()> is passed a HashRef with the following options: |
|
3086
|
|
|
|
|
|
|
|
|
3087
|
|
|
|
|
|
|
-input => $cp->pod_filename, |
|
3088
|
|
|
|
|
|
|
-output => <filehandle>, |
|
3089
|
|
|
|
|
|
|
-exitval => 'NOEXIT', |
|
3090
|
|
|
|
|
|
|
-verbose => 0, |
|
3091
|
|
|
|
|
|
|
|
|
3092
|
|
|
|
|
|
|
This set of options causes B<pod2usage()> to format the B<SYNOPSIS> |
|
3093
|
|
|
|
|
|
|
portion of the user's POD. Any key-value pairs in |
|
3094
|
|
|
|
|
|
|
B<%optional_supplements> are appended to the contents of the HashRef, |
|
3095
|
|
|
|
|
|
|
allowing you to override or supplement these defaults. |
|
3096
|
|
|
|
|
|
|
|
|
3097
|
|
|
|
|
|
|
=head3 Example |
|
3098
|
|
|
|
|
|
|
|
|
3099
|
|
|
|
|
|
|
Internally, B<Carp::Proxy> uses B<synopsis()> to extract sections from this |
|
3100
|
|
|
|
|
|
|
POD document when composing diagnostics. If, for instance, you supply a |
|
3101
|
|
|
|
|
|
|
negative value as the setting for L<body_indent|/body_indent> you get an |
|
3102
|
|
|
|
|
|
|
exception. The text of the exception is generated using something like |
|
3103
|
|
|
|
|
|
|
this: |
|
3104
|
|
|
|
|
|
|
|
|
3105
|
|
|
|
|
|
|
$cp->synopsis( -verbose => 99, |
|
3106
|
|
|
|
|
|
|
-sections => ["ATTRIBUTES/body_indent"], |
|
3107
|
|
|
|
|
|
|
); |
|
3108
|
|
|
|
|
|
|
|
|
3109
|
|
|
|
|
|
|
The resulting diagnostic looks something like this: |
|
3110
|
|
|
|
|
|
|
|
|
3111
|
|
|
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
3112
|
|
|
|
|
|
|
Oops << negative body indentation >> |
|
3113
|
|
|
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
3114
|
|
|
|
|
|
|
*** Description *** |
|
3115
|
|
|
|
|
|
|
The requested setting of '-1' for the 'body_indent' |
|
3116
|
|
|
|
|
|
|
attribute is not allowed. |
|
3117
|
|
|
|
|
|
|
|
|
3118
|
|
|
|
|
|
|
*** Synopsis *** |
|
3119
|
|
|
|
|
|
|
body_indent: |
|
3120
|
|
|
|
|
|
|
*body_indent* influences the presentation of paragraphs |
|
3121
|
|
|
|
|
|
|
created by the Section creating methods filled() and |
|
3122
|
|
|
|
|
|
|
fixed(). Use *body_indent* to determine the amount of |
|
3123
|
|
|
|
|
|
|
additional indentation, beyond header_indent, that is |
|
3124
|
|
|
|
|
|
|
applied to Section paragraphs. |
|
3125
|
|
|
|
|
|
|
|
|
3126
|
|
|
|
|
|
|
Builder: _build_body_indent() |
|
3127
|
|
|
|
|
|
|
Default: 2 |
|
3128
|
|
|
|
|
|
|
Domain: Non-negative integers |
|
3129
|
|
|
|
|
|
|
Affects: filled_section() and fixed_section() |
|
3130
|
|
|
|
|
|
|
Mutability: Read-Write |
|
3131
|
|
|
|
|
|
|
|
|
3132
|
|
|
|
|
|
|
*** Stacktrace *** |
|
3133
|
|
|
|
|
|
|
... |
|
3134
|
|
|
|
|
|
|
|
|
3135
|
|
|
|
|
|
|
See L<'perldoc Pod::Usage'|Pod::Usage> and |
|
3136
|
|
|
|
|
|
|
L<'perldoc Pod::Select'|Pod::Select> for details about using B<-verbose> |
|
3137
|
|
|
|
|
|
|
and B<-sections>. |
|
3138
|
|
|
|
|
|
|
|
|
3139
|
|
|
|
|
|
|
=head2 usage |
|
3140
|
|
|
|
|
|
|
|
|
3141
|
|
|
|
|
|
|
Usage: |
|
3142
|
|
|
|
|
|
|
<void> $cp->usage(); |
|
3143
|
|
|
|
|
|
|
|
|
3144
|
|
|
|
|
|
|
B<usage()> examines the callstack, to find the invoker - the subroutine |
|
3145
|
|
|
|
|
|
|
that invoked the Proxy. A pass through the |
|
3146
|
|
|
|
|
|
|
L<HANDLER SEARCH|/HANDLER-SEARCH:> algorithm is made to see if it can find |
|
3147
|
|
|
|
|
|
|
a subroutine with this name: |
|
3148
|
|
|
|
|
|
|
|
|
3149
|
|
|
|
|
|
|
usage_<invoker> |
|
3150
|
|
|
|
|
|
|
|
|
3151
|
|
|
|
|
|
|
In the default configuration this means that these three subroutine |
|
3152
|
|
|
|
|
|
|
names are tested for existence: |
|
3153
|
|
|
|
|
|
|
|
|
3154
|
|
|
|
|
|
|
<package>::_cp_usage_<invoker> |
|
3155
|
|
|
|
|
|
|
<package>::_usage_<invoker> |
|
3156
|
|
|
|
|
|
|
<package>::usage_<invoker> |
|
3157
|
|
|
|
|
|
|
|
|
3158
|
|
|
|
|
|
|
Just like the search for a Handler, the settings for |
|
3159
|
|
|
|
|
|
|
L<handler_prefix|/handler_prefix> and |
|
3160
|
|
|
|
|
|
|
L<handler_pkgs|/handler_pkgs> influence the where and what of |
|
3161
|
|
|
|
|
|
|
the search for a usage subroutine. |
|
3162
|
|
|
|
|
|
|
|
|
3163
|
|
|
|
|
|
|
If none of the attempts finds an existing subroutine then the next entry in |
|
3164
|
|
|
|
|
|
|
the callstack (i.e. the invoker of the invoker) is tried. The progression |
|
3165
|
|
|
|
|
|
|
up the callstack continues until there are no more stackframes. At this |
|
3166
|
|
|
|
|
|
|
point the algorithm gives up and throws a "no usage documentation" exception. |
|
3167
|
|
|
|
|
|
|
|
|
3168
|
|
|
|
|
|
|
The search sounds complex, but the intent is simple: public subroutines |
|
3169
|
|
|
|
|
|
|
and methods can call utilities, say to validate incoming arguments, and |
|
3170
|
|
|
|
|
|
|
these utilities can call Proxys to throw exceptions. When the Handler |
|
3171
|
|
|
|
|
|
|
invokes B<usage()> we eventually find a usage message associated with the |
|
3172
|
|
|
|
|
|
|
public subroutine. |
|
3173
|
|
|
|
|
|
|
|
|
3174
|
|
|
|
|
|
|
#----- We want this to be called for help with 'my_func()' |
|
3175
|
|
|
|
|
|
|
sub _usage_my_func { |
|
3176
|
|
|
|
|
|
|
my( $cp ) = @_; |
|
3177
|
|
|
|
|
|
|
|
|
3178
|
|
|
|
|
|
|
$cp->fixed( 'Usage: <num> my_func( val );', 'Usage' ); |
|
3179
|
|
|
|
|
|
|
$cp->filled( 'my_func() returns blah blah blah.', '' ); |
|
3180
|
|
|
|
|
|
|
} |
|
3181
|
|
|
|
|
|
|
|
|
3182
|
|
|
|
|
|
|
sub my_func { |
|
3183
|
|
|
|
|
|
|
my( $val ) = @_; |
|
3184
|
|
|
|
|
|
|
|
|
3185
|
|
|
|
|
|
|
fatal 'missing_argument', 'val' |
|
3186
|
|
|
|
|
|
|
if not defined $val; |
|
3187
|
|
|
|
|
|
|
... |
|
3188
|
|
|
|
|
|
|
} |
|
3189
|
|
|
|
|
|
|
|
|
3190
|
|
|
|
|
|
|
#----- Reusable by anyone that defines their own _usage_ |
|
3191
|
|
|
|
|
|
|
sub _cp_missing_argument { |
|
3192
|
|
|
|
|
|
|
my( $cp, $name ) = @_; |
|
3193
|
|
|
|
|
|
|
|
|
3194
|
|
|
|
|
|
|
$cp->filled("The argument '$name' is missing, or undef."); |
|
3195
|
|
|
|
|
|
|
$cp->usage; |
|
3196
|
|
|
|
|
|
|
} |
|
3197
|
|
|
|
|
|
|
|
|
3198
|
|
|
|
|
|
|
Other subroutines, besides my_func(), can throw fatal exceptions with the |
|
3199
|
|
|
|
|
|
|
'missing_argument' Handler. The diagnostic will be customized |
|
3200
|
|
|
|
|
|
|
appropriately for each one. |
|
3201
|
|
|
|
|
|
|
|
|
3202
|
|
|
|
|
|
|
The invoker-upward aspect of the search means that B<my_func()>, instead |
|
3203
|
|
|
|
|
|
|
of calling B<fatal()> directly, could have called an arg-checking utility, |
|
3204
|
|
|
|
|
|
|
which called another utility etc., which finally called B<fatal()>. The |
|
3205
|
|
|
|
|
|
|
search would have eventually located B<_usage_my_func()>. |
|
3206
|
|
|
|
|
|
|
|
|
3207
|
|
|
|
|
|
|
=head1 HANDLER SEARCH |
|
3208
|
|
|
|
|
|
|
|
|
3209
|
|
|
|
|
|
|
A Proxy invocation contains, as its first argument, a string that will |
|
3210
|
|
|
|
|
|
|
become the L<handler_name|/handler_name> attribute. The string |
|
3211
|
|
|
|
|
|
|
C<'no_such_author'> is used to establish |
|
3212
|
|
|
|
|
|
|
L<handler_name|/handler_name> in this example: |
|
3213
|
|
|
|
|
|
|
|
|
3214
|
|
|
|
|
|
|
fatal 'no_such_author', $who; |
|
3215
|
|
|
|
|
|
|
|
|
3216
|
|
|
|
|
|
|
The Proxy calls the Handler to build up the diagnostic message, but first |
|
3217
|
|
|
|
|
|
|
it must locate the requested subroutine. |
|
3218
|
|
|
|
|
|
|
|
|
3219
|
|
|
|
|
|
|
The search for a Handler subroutine is made in the packages found in |
|
3220
|
|
|
|
|
|
|
L<handler_pkgs|/handler_pkgs>. Users can specify a list of |
|
3221
|
|
|
|
|
|
|
packages to search by supplying the tagged list to B<use()> or |
|
3222
|
|
|
|
|
|
|
L<import()|/import>. |
|
3223
|
|
|
|
|
|
|
|
|
3224
|
|
|
|
|
|
|
package main; |
|
3225
|
|
|
|
|
|
|
use Carp::Proxy fatal => { handler_pkgs => [qw( Support Common )]}; |
|
3226
|
|
|
|
|
|
|
|
|
3227
|
|
|
|
|
|
|
You can also sub-class B<Carp::Proxy> and override |
|
3228
|
|
|
|
|
|
|
B<_build_handler_pkgs()> to return an ArrayRef of the desired packages. |
|
3229
|
|
|
|
|
|
|
|
|
3230
|
|
|
|
|
|
|
The Proxy always appends a copy of |
|
3231
|
|
|
|
|
|
|
L<proxy_package|/proxy_package> to |
|
3232
|
|
|
|
|
|
|
L<handler_pkgs|/handler_pkgs> after object construction. |
|
3233
|
|
|
|
|
|
|
L<proxy_package|/proxy_package> is the package that issued the |
|
3234
|
|
|
|
|
|
|
B<use()>, or made the call to L<import()|/import>. In the above example |
|
3235
|
|
|
|
|
|
|
L<handler_pkgs|/handler_pkgs> becomes: |
|
3236
|
|
|
|
|
|
|
|
|
3237
|
|
|
|
|
|
|
[qw( Support Common main )] |
|
3238
|
|
|
|
|
|
|
|
|
3239
|
|
|
|
|
|
|
The subroutine that is the target of the search is influenced by the |
|
3240
|
|
|
|
|
|
|
setting of L<handler_prefix|/handler_prefix>. When the |
|
3241
|
|
|
|
|
|
|
L<handler_prefix|/handler_prefix> attribute is undef, the Proxy |
|
3242
|
|
|
|
|
|
|
builds three templates from L<handler_name|/handler_name>. The |
|
3243
|
|
|
|
|
|
|
first subroutine that exists is used as the Handler. |
|
3244
|
|
|
|
|
|
|
|
|
3245
|
|
|
|
|
|
|
<package>::_cp_<handler_name> |
|
3246
|
|
|
|
|
|
|
<package>::_<handler_name> |
|
3247
|
|
|
|
|
|
|
<package>::<handler_name> |
|
3248
|
|
|
|
|
|
|
|
|
3249
|
|
|
|
|
|
|
If L<handler_prefix|/handler_prefix> is not undef then only one |
|
3250
|
|
|
|
|
|
|
template is tried: |
|
3251
|
|
|
|
|
|
|
|
|
3252
|
|
|
|
|
|
|
<package>::<handler_prefix><handler_name> |
|
3253
|
|
|
|
|
|
|
|
|
3254
|
|
|
|
|
|
|
If a Handler subroutine is not found by the template search then a check |
|
3255
|
|
|
|
|
|
|
is made to see if L<handler_name|/handler_name> matches one of |
|
3256
|
|
|
|
|
|
|
the B<Carp::Proxy> builtin Handlers. The builtin Handlers are surrounded |
|
3257
|
|
|
|
|
|
|
by C<'*'> characters since those are guaranteed not to collide with user |
|
3258
|
|
|
|
|
|
|
Handlers. |
|
3259
|
|
|
|
|
|
|
|
|
3260
|
|
|
|
|
|
|
*assertion_failure* |
|
3261
|
|
|
|
|
|
|
*internal_error* |
|
3262
|
|
|
|
|
|
|
*configuration* |
|
3263
|
|
|
|
|
|
|
|
|
3264
|
|
|
|
|
|
|
See L<BUILTIN HANDLERS|/BUILTIN-HANDLERS:> for a description of their |
|
3265
|
|
|
|
|
|
|
functionality. |
|
3266
|
|
|
|
|
|
|
|
|
3267
|
|
|
|
|
|
|
Finally, if a suitable Handler is not found by any of the above searches |
|
3268
|
|
|
|
|
|
|
the Proxy concludes that you forgot to define a Handler. In response, the |
|
3269
|
|
|
|
|
|
|
Proxy attempts to shame you into compliance by throwing an exception of |
|
3270
|
|
|
|
|
|
|
its own: |
|
3271
|
|
|
|
|
|
|
|
|
3272
|
|
|
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
3273
|
|
|
|
|
|
|
Oops << embarrassed developers >> |
|
3274
|
|
|
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
3275
|
|
|
|
|
|
|
*** Description *** |
|
3276
|
|
|
|
|
|
|
There was an error. The developers caught the error and |
|
3277
|
|
|
|
|
|
|
attempted to pass diagnosis off to a handler. Unfortunately |
|
3278
|
|
|
|
|
|
|
they forgot to define the handler. Now there are two |
|
3279
|
|
|
|
|
|
|
errors. You should complain! |
|
3280
|
|
|
|
|
|
|
|
|
3281
|
|
|
|
|
|
|
*** Please contact the maintainer *** |
|
3282
|
|
|
|
|
|
|
your.name@support.org 555-1212 |
|
3283
|
|
|
|
|
|
|
|
|
3284
|
|
|
|
|
|
|
*** Missing Handler *** |
|
3285
|
|
|
|
|
|
|
handler_name: no_credentials |
|
3286
|
|
|
|
|
|
|
handler_pkgs: main |
|
3287
|
|
|
|
|
|
|
handler_prefix: (undef) |
|
3288
|
|
|
|
|
|
|
|
|
3289
|
|
|
|
|
|
|
*** Stacktrace *** |
|
3290
|
|
|
|
|
|
|
fatal called from line 443 of /usr/local/bin/hibs |
|
3291
|
|
|
|
|
|
|
validate_user called from line 510 of /usr/local/bin/hibs |
|
3292
|
|
|
|
|
|
|
cmdline called from line 216 of /usr/local/bin/hibs |
|
3293
|
|
|
|
|
|
|
main called from line 17 of /usr/local/bin/hibs |
|
3294
|
|
|
|
|
|
|
|
|
3295
|
|
|
|
|
|
|
=head1 BUILTIN HANDLERS |
|
3296
|
|
|
|
|
|
|
|
|
3297
|
|
|
|
|
|
|
These are handler subroutines that come with B<Carp::Proxy>. |
|
3298
|
|
|
|
|
|
|
|
|
3299
|
|
|
|
|
|
|
=head2 internal_error |
|
3300
|
|
|
|
|
|
|
|
|
3301
|
|
|
|
|
|
|
Usage: |
|
3302
|
|
|
|
|
|
|
<void> fatal '*internal_error*', @strings; |
|
3303
|
|
|
|
|
|
|
|
|
3304
|
|
|
|
|
|
|
The C<'*internal_error*'> Handler can be used to promote warnings to |
|
3305
|
|
|
|
|
|
|
errors or to turn miscellaneous B<die()> exceptions to full B<Carp::Proxy> |
|
3306
|
|
|
|
|
|
|
exceptions. The typical use is to trap B<$SIG{__DIE__}> or |
|
3307
|
|
|
|
|
|
|
B<$SIG{__WARN__}>. |
|
3308
|
|
|
|
|
|
|
|
|
3309
|
|
|
|
|
|
|
use English; |
|
3310
|
|
|
|
|
|
|
|
|
3311
|
|
|
|
|
|
|
$SIG{__DIE__} = sub{ |
|
3312
|
|
|
|
|
|
|
|
|
3313
|
|
|
|
|
|
|
fatal '*internal_error*', @_ |
|
3314
|
|
|
|
|
|
|
if not $EXCEPTIONS_BEING_CAUGHT; |
|
3315
|
|
|
|
|
|
|
}; |
|
3316
|
|
|
|
|
|
|
|
|
3317
|
|
|
|
|
|
|
A Filled Section is generated from the string interpolation of |
|
3318
|
|
|
|
|
|
|
I<@strings>. In the above example, the argument is the message that was |
|
3319
|
|
|
|
|
|
|
passed to B<die()>, like "Illegal division by zero". A |
|
3320
|
|
|
|
|
|
|
L<contact_maintainer()|/contact_maintainer> Section is also added. |
|
3321
|
|
|
|
|
|
|
|
|
3322
|
|
|
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
3323
|
|
|
|
|
|
|
Fatal: << internal error >> |
|
3324
|
|
|
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
3325
|
|
|
|
|
|
|
*** Description *** |
|
3326
|
|
|
|
|
|
|
Illegal division by zero at ./combine_decks line 27. |
|
3327
|
|
|
|
|
|
|
|
|
3328
|
|
|
|
|
|
|
*** Please contact the maintainer *** |
|
3329
|
|
|
|
|
|
|
your.name@support.org 555-1212 |
|
3330
|
|
|
|
|
|
|
|
|
3331
|
|
|
|
|
|
|
*** Stacktrace *** |
|
3332
|
|
|
|
|
|
|
... |
|
3333
|
|
|
|
|
|
|
|
|
3334
|
|
|
|
|
|
|
=head2 assertion_failure |
|
3335
|
|
|
|
|
|
|
|
|
3336
|
|
|
|
|
|
|
Usage: |
|
3337
|
|
|
|
|
|
|
<void> fatal '*assertion_failure*', $description <, $hashref>; |
|
3338
|
|
|
|
|
|
|
|
|
3339
|
|
|
|
|
|
|
If a failing assertion is indicative of a programmer fault then the |
|
3340
|
|
|
|
|
|
|
primary audience for a diagnostic message will be a maintainer rather than |
|
3341
|
|
|
|
|
|
|
an end user. Maintainers are most often helped by knowledge of the |
|
3342
|
|
|
|
|
|
|
surrounding state. The builtin Handler B<*assertion_failure*> attempts to |
|
3343
|
|
|
|
|
|
|
be a generic Handler, useful for transmitting state to maintainers. |
|
3344
|
|
|
|
|
|
|
|
|
3345
|
|
|
|
|
|
|
Using B<*assertion_failure*> frees the programmer from having to write a |
|
3346
|
|
|
|
|
|
|
Handler. The tradeoff is that some ability to customize the diagnostic is |
|
3347
|
|
|
|
|
|
|
lost and the invocation syntax is more cluttered. The tradeoff can be |
|
3348
|
|
|
|
|
|
|
reasonable for events that are rarely triggered, especially if it |
|
3349
|
|
|
|
|
|
|
encourages programmers to add more assertions. |
|
3350
|
|
|
|
|
|
|
|
|
3351
|
|
|
|
|
|
|
B<'*assertion_failure*'> produces a Filled Section with some boilerplate |
|
3352
|
|
|
|
|
|
|
containing the supplied I<$description>. |
|
3353
|
|
|
|
|
|
|
|
|
3354
|
|
|
|
|
|
|
Also included is a Fixed Section which contains a YAML dump of |
|
3355
|
|
|
|
|
|
|
I<$hashref>. This works best when the HashRef keys act as informational |
|
3356
|
|
|
|
|
|
|
names (tag=>value pairs) to convey state. YAML is nice here because it |
|
3357
|
|
|
|
|
|
|
does a great job of serializing complex data structures. |
|
3358
|
|
|
|
|
|
|
|
|
3359
|
|
|
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
3360
|
|
|
|
|
|
|
Fatal: << assertion failure >> |
|
3361
|
|
|
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
3362
|
|
|
|
|
|
|
*** Description *** |
|
3363
|
|
|
|
|
|
|
An assertion has failed. This indicates that the internal |
|
3364
|
|
|
|
|
|
|
state of the program is corrupt. |
|
3365
|
|
|
|
|
|
|
|
|
3366
|
|
|
|
|
|
|
<$description> |
|
3367
|
|
|
|
|
|
|
|
|
3368
|
|
|
|
|
|
|
*** Please contact the maintainer *** |
|
3369
|
|
|
|
|
|
|
your.name@support.org 555-1212 |
|
3370
|
|
|
|
|
|
|
|
|
3371
|
|
|
|
|
|
|
*** Salient State (YAML) *** |
|
3372
|
|
|
|
|
|
|
--- |
|
3373
|
|
|
|
|
|
|
failure: 'unmatched case' |
|
3374
|
|
|
|
|
|
|
index: 27 |
|
3375
|
|
|
|
|
|
|
selection: 'brunch' |
|
3376
|
|
|
|
|
|
|
|
|
3377
|
|
|
|
|
|
|
*** Stacktrace *** |
|
3378
|
|
|
|
|
|
|
... |
|
3379
|
|
|
|
|
|
|
|
|
3380
|
|
|
|
|
|
|
=head2 configuration |
|
3381
|
|
|
|
|
|
|
|
|
3382
|
|
|
|
|
|
|
Usage: |
|
3383
|
|
|
|
|
|
|
<HashRef> fatal '*configuration*'; |
|
3384
|
|
|
|
|
|
|
|
|
3385
|
|
|
|
|
|
|
The C<'*configuration*'> Handler is unconventional in that no exception is |
|
3386
|
|
|
|
|
|
|
thrown. Instead, a reference to an internal hash is returned to the |
|
3387
|
|
|
|
|
|
|
calling environment. Any changes to the referenced hash affect all future |
|
3388
|
|
|
|
|
|
|
Proxy invocations. |
|
3389
|
|
|
|
|
|
|
|
|
3390
|
|
|
|
|
|
|
Proxy configuration is established when a Proxy is created - either during |
|
3391
|
|
|
|
|
|
|
B<use()> or L<import()|/import>. Configuration consists of attribute |
|
3392
|
|
|
|
|
|
|
=E<gt> parameter pairs that are supplied by the user. |
|
3393
|
|
|
|
|
|
|
|
|
3394
|
|
|
|
|
|
|
use Carp::Proxy ( warning => { banner_title => 'Warning', |
|
3395
|
|
|
|
|
|
|
disposition => 'warn' }); |
|
3396
|
|
|
|
|
|
|
|
|
3397
|
|
|
|
|
|
|
In the above snippet, L<banner_title|/banner_title> and |
|
3398
|
|
|
|
|
|
|
L<disposition|/disposition>, are internally held in a |
|
3399
|
|
|
|
|
|
|
closure-based hash that persists across all invocations of the Proxy. The |
|
3400
|
|
|
|
|
|
|
B<*configuration*> Handler causes the Proxy to return a reference to this |
|
3401
|
|
|
|
|
|
|
internal hash. |
|
3402
|
|
|
|
|
|
|
|
|
3403
|
|
|
|
|
|
|
Here is an example of wanting to change Proxy behavior after Proxy |
|
3404
|
|
|
|
|
|
|
creation: |
|
3405
|
|
|
|
|
|
|
|
|
3406
|
|
|
|
|
|
|
#----- fatal() does NOT throw an exception here... |
|
3407
|
|
|
|
|
|
|
my $config = fatal '*configuration*'; |
|
3408
|
|
|
|
|
|
|
|
|
3409
|
|
|
|
|
|
|
$config->{ disposition } = \&GUI::as_dialog; |
|
3410
|
|
|
|
|
|
|
|
|
3411
|
|
|
|
|
|
|
As alluded to above, we want our GUI program to use conventional STDERR |
|
3412
|
|
|
|
|
|
|
based messages during initialization, but once the GUI is up we want |
|
3413
|
|
|
|
|
|
|
future messages to go to a dialog widget. |
|
3414
|
|
|
|
|
|
|
|
|
3415
|
|
|
|
|
|
|
=head1 BUGS AND LIMITATIONS |
|
3416
|
|
|
|
|
|
|
|
|
3417
|
|
|
|
|
|
|
Please report any bugs or feature requests to C<bug-carp-proxy at |
|
3418
|
|
|
|
|
|
|
rt.cpan.org>, or through the web interface at |
|
3419
|
|
|
|
|
|
|
L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Carp-Proxy>. I will be |
|
3420
|
|
|
|
|
|
|
notified, and then you'll automatically be notified of progress on your |
|
3421
|
|
|
|
|
|
|
bug as I make changes. |
|
3422
|
|
|
|
|
|
|
|
|
3423
|
|
|
|
|
|
|
=head1 DEPENDENCIES |
|
3424
|
|
|
|
|
|
|
|
|
3425
|
|
|
|
|
|
|
Core dependencies (come with Perl) |
|
3426
|
|
|
|
|
|
|
|
|
3427
|
|
|
|
|
|
|
Config |
|
3428
|
|
|
|
|
|
|
Cwd |
|
3429
|
|
|
|
|
|
|
English |
|
3430
|
|
|
|
|
|
|
overload |
|
3431
|
|
|
|
|
|
|
Pod::Usage |
|
3432
|
|
|
|
|
|
|
|
|
3433
|
|
|
|
|
|
|
External dependencies (install from CPAN) |
|
3434
|
|
|
|
|
|
|
|
|
3435
|
|
|
|
|
|
|
Moose |
|
3436
|
|
|
|
|
|
|
Readonly |
|
3437
|
|
|
|
|
|
|
Sub::Name |
|
3438
|
|
|
|
|
|
|
YAML::XS |
|
3439
|
|
|
|
|
|
|
|
|
3440
|
|
|
|
|
|
|
=head1 SUPPORT |
|
3441
|
|
|
|
|
|
|
|
|
3442
|
|
|
|
|
|
|
You can find documentation for this module with the perldoc command. |
|
3443
|
|
|
|
|
|
|
|
|
3444
|
|
|
|
|
|
|
perldoc Carp::Proxy |
|
3445
|
|
|
|
|
|
|
|
|
3446
|
|
|
|
|
|
|
|
|
3447
|
|
|
|
|
|
|
You can also look for information at: |
|
3448
|
|
|
|
|
|
|
|
|
3449
|
|
|
|
|
|
|
=over 4 |
|
3450
|
|
|
|
|
|
|
|
|
3451
|
|
|
|
|
|
|
=item * RT: CPAN's request tracker (report bugs here) |
|
3452
|
|
|
|
|
|
|
|
|
3453
|
|
|
|
|
|
|
L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Carp-Proxy> |
|
3454
|
|
|
|
|
|
|
|
|
3455
|
|
|
|
|
|
|
=item * AnnoCPAN: Annotated CPAN documentation |
|
3456
|
|
|
|
|
|
|
|
|
3457
|
|
|
|
|
|
|
L<http://annocpan.org/dist/Carp-Proxy> |
|
3458
|
|
|
|
|
|
|
|
|
3459
|
|
|
|
|
|
|
=item * CPAN Ratings |
|
3460
|
|
|
|
|
|
|
|
|
3461
|
|
|
|
|
|
|
L<http://cpanratings.perl.org/d/Carp-Proxy> |
|
3462
|
|
|
|
|
|
|
|
|
3463
|
|
|
|
|
|
|
=item * Search CPAN |
|
3464
|
|
|
|
|
|
|
|
|
3465
|
|
|
|
|
|
|
L<http://search.cpan.org/dist/Carp-Proxy/> |
|
3466
|
|
|
|
|
|
|
|
|
3467
|
|
|
|
|
|
|
=back |
|
3468
|
|
|
|
|
|
|
|
|
3469
|
|
|
|
|
|
|
|
|
3470
|
|
|
|
|
|
|
=head1 SEE ALSO |
|
3471
|
|
|
|
|
|
|
|
|
3472
|
|
|
|
|
|
|
=over 4 |
|
3473
|
|
|
|
|
|
|
|
|
3474
|
|
|
|
|
|
|
=item perldoc L<perlvar> |
|
3475
|
|
|
|
|
|
|
|
|
3476
|
|
|
|
|
|
|
The section on $CHILD_ERROR describes information packing when a child |
|
3477
|
|
|
|
|
|
|
process terminates. This is used by |
|
3478
|
|
|
|
|
|
|
L<decipher_child_error()|/decipher_child_error>. |
|
3479
|
|
|
|
|
|
|
|
|
3480
|
|
|
|
|
|
|
=item perldoc -f die |
|
3481
|
|
|
|
|
|
|
|
|
3482
|
|
|
|
|
|
|
The documentation on Perl's B<die()> details how the exit code for a process |
|
3483
|
|
|
|
|
|
|
depends on B<$ERRNO> and B<$CHILD_ERROR>. |
|
3484
|
|
|
|
|
|
|
|
|
3485
|
|
|
|
|
|
|
=item perldoc L<Pod::Usage> |
|
3486
|
|
|
|
|
|
|
|
|
3487
|
|
|
|
|
|
|
The L<synopsis()|/synopsis> method calls B<pod2usage()> to format |
|
3488
|
|
|
|
|
|
|
the B<SYNOPSIS> section from user POD. |
|
3489
|
|
|
|
|
|
|
|
|
3490
|
|
|
|
|
|
|
=item perldoc L<YAML::XS> |
|
3491
|
|
|
|
|
|
|
|
|
3492
|
|
|
|
|
|
|
The L<as_yaml|/as_yaml> attribute produces a YAML Dump of the |
|
3493
|
|
|
|
|
|
|
B<Carp::Proxy> object so that it can be reconstituted later. |
|
3494
|
|
|
|
|
|
|
|
|
3495
|
|
|
|
|
|
|
The L<*assertion_failure*|/assertion_failure> builtin |
|
3496
|
|
|
|
|
|
|
Handler produces a Section containing YAML Dump of a user HashRef. |
|
3497
|
|
|
|
|
|
|
|
|
3498
|
|
|
|
|
|
|
=item perldoc L<Carp> |
|
3499
|
|
|
|
|
|
|
|
|
3500
|
|
|
|
|
|
|
The 'croak' and 'confess' concepts were originated by B<Carp>. If you are |
|
3501
|
|
|
|
|
|
|
making a Do-it-yourself CodeRef for L<context|/context> then |
|
3502
|
|
|
|
|
|
|
B<Carp>'s B<longmess()> or B<longmess_heavy()> may prove useful. |
|
3503
|
|
|
|
|
|
|
|
|
3504
|
|
|
|
|
|
|
=back |
|
3505
|
|
|
|
|
|
|
|
|
3506
|
|
|
|
|
|
|
=head1 LICENSE AND COPYRIGHT |
|
3507
|
|
|
|
|
|
|
|
|
3508
|
|
|
|
|
|
|
Copyright 2014-2015 Paul Liebert. |
|
3509
|
|
|
|
|
|
|
|
|
3510
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it |
|
3511
|
|
|
|
|
|
|
under the terms of either: the GNU General Public License as published |
|
3512
|
|
|
|
|
|
|
by the Free Software Foundation; or the Artistic License. |
|
3513
|
|
|
|
|
|
|
|
|
3514
|
|
|
|
|
|
|
See http://dev.perl.org/licenses/ for more information. |
|
3515
|
|
|
|
|
|
|
|
|
3516
|
|
|
|
|
|
|
=cut |