File Coverage

blib/lib/Assert/Conditional/Utils.pm
Criterion Covered Total %
statement 377 447 84.3
branch 30 80 37.5
condition 27 89 30.3
subroutine 115 132 87.1
pod 30 39 76.9
total 579 787 73.5


line stmt bran cond sub pod time code
1             package Assert::Conditional::Utils;
2              
3 3     3   40 use v5.12;
  3         19  
4 3     3   16 use utf8;
  3         6  
  3         18  
5 3     3   67 use strict;
  3         6  
  3         92  
6 3     3   18 use warnings;
  3         7  
  3         99  
7              
8 3     3   18 use B::Deparse;
  3         7  
  3         102  
9 3     3   14 use Carp qw(carp cluck croak confess shortmess longmess);
  3         6  
  3         245  
10 3     3   19 use Cwd qw(cwd abs_path);
  3         6  
  3         188  
11 3     3   20 use Exporter qw(import);
  3         6  
  3         125  
12 3     3   21 use File::Basename qw(basename dirname);
  3         6  
  3         220  
13 3     3   27 use File::Spec;
  3         5  
  3         1258  
14              
15             #################################################################
16              
17             sub botch ( $ ) ;
18             sub botch_argc ( $$ ) ;
19             sub botch_array_length ( $$ ) ;
20             sub botch_false ( ) ;
21             sub botch_have_thing_wanted ( @ ) ;
22             sub botch_undef ( ) ;
23             sub code_of_coderef ( $ ) ;
24             sub commify_and ;
25             sub commify_but ;
26             sub commify_nor ;
27             sub commify_or ;
28             sub commify_series ;
29             sub dump_exports ( @ ) ;
30             sub dump_package_exports ( $@ ) ;
31             sub Export ;
32             sub FIXME ( ) ;
33             sub _get_comparitor ( $ ) ;
34             sub his_args ( ;$ ) ;
35             sub his_assert ( ) ;
36             sub his_context ( ;$ ) ;
37             sub his_filename ( ;$ ) ;
38             sub his_frame ( ;$ ) ;
39             sub his_is_require ( ;$ ) ;
40             sub his_line ( ;$ ) ;
41             sub his_package ( ;$ ) ;
42             sub his_sub ( ;$ ) ;
43             sub his_subroutine ( ;$ ) ;
44             sub _init_envariables ( ) ;
45             sub _init_public_vars ( ) ;
46             sub name_of_coderef ( $ ) ;
47             sub NOT_REACHED ( ) ;
48             sub panic ( $ ) ;
49             sub quotify_and ;
50             sub quotify_but ;
51             sub quotify_nor ;
52             sub quotify_or ;
53             sub serialize_conjunction ( $@ ) ;
54             sub sig_name2num ( $ ) ;
55             sub sig_num2longname ( $ ) ;
56             sub sig_num2name ( $ ) ;
57             sub subname_or_code ( $ ) ;
58             sub UCA ( _ ) ;
59             sub UCA1 ( _ ) ;
60             sub uca1_cmp ( $$ ) ;
61             sub UCA2 ( _ ) ;
62             sub uca2_cmp ( $$ ) ;
63             sub UCA3 ( _ ) ;
64             sub uca3_cmp ( $$ ) ;
65             sub UCA4 ( _ ) ;
66             sub uca4_cmp ( $$ ) ;
67             sub uca_cmp ( $$ ) ;
68             sub uca_sort ( @ ) ;
69             sub _uniq ;
70              
71             #################################################################
72              
73 3     3   22 use version 0.77;
  3         50  
  3         20  
74             our $VERSION = version->declare("0.010");
75              
76             our %EXPORT_TAGS;
77              
78             push our @EXPORT_OK, do {
79             my %seen;
80             grep { !$seen{$_}++ } map { @$_ } values %EXPORT_TAGS;
81             };
82              
83             our @CARP_NOT = qw(
84             Assert::Conditional::Utils
85             Assert::Conditional
86             Attribute::Handlers
87             );
88              
89             $EXPORT_TAGS{all} = \@EXPORT_OK;
90              
91             #################################################################
92              
93 3     3   632 use Attribute::Handlers;
  3         7  
  3         17  
94              
95             # The following attribute handler handler for subs saves
96             # us a lot of bookkeeping trouble by letting us declare
97             # which export tag groups a particular assert belongs to
98             # at the point of declaration where it belongs, and so
99             # that it is all handled automatically.
100              
101             sub Export : ATTR(BEGIN)
102             {
103 162     162 1 105420 our $Assert_Debug;
104 162         536 my($package, $symbol, $referent, $attr, $data, $phase, $filename, $linenum) = @_;
105              
106 162         270 state $glyph_map = {
107             CODE => '&',
108             SCALAR => '$',
109             ARRAY => '@',
110             HASH => '%',
111             };
112              
113 162   33     508 my $glyph = $glyph_map->{ ref($referent) } || botch_undef;
114              
115 3     3   428 no strict "refs";
  3         29  
  3         750  
116              
117 162         240 my $exportee = *{$symbol}{NAME};
  162         377  
118 162 100       508 $exportee =~ s/^/$glyph/ unless $glyph eq $glyph_map->{CODE};
119              
120 162         288 my $tagref = $data;
121 162 50 33     745 if (defined($tagref) && !ref($tagref)) {
122 0         0 $tagref = [ $tagref ];
123             }
124              
125 162   33     445 my $debugging = $Exporter::Verbose || $Assert_Debug;
126              
127 162         326 my $his_export_ok = $package . "::EXPORT_OK";
128 162         594 push @$his_export_ok, $exportee;
129 162 50       314 carp "Adding $exportee to EXPORT_OK in $package at ",__FILE__," line ",__LINE__ if $debugging;
130              
131 162 50       312 if ($tagref) {
132 162         240 my $his_export_tags = $package . "::EXPORT_TAGS";
133 162         357 for my $tag (@$tagref, qw(all)) {
134 330 50       576 carp "Adding $exportee to EXPORT_TAG :$tag in $package at ",__FILE__," line ",__LINE__ if $debugging;
135 330         404 push @{ $his_export_tags->{$tag} }, $exportee;
  330         1307  
136             }
137             }
138 3     3   23 }
  3         24  
  3         23  
139              
140             # Yes, you can actually export these that way too.
141             our($Assert_Debug, $Assert_Always, $Assert_Carp, $Assert_Never, $Allow_Handlers)
142 3     3   2092 :Export( qw[vars] );
  3     3   7  
  3     3   21  
  3     3   373  
  3     3   10  
  3         25  
  3         320  
  3         6  
  3         12  
  3         297  
  3         7  
  3         21  
  3         354  
  3         6  
  3         14  
143              
144             our $Pod_Generation;
145              
146             # Let's not talk about these ones.
147             our(%PLURAL, %N_PLURAL)
148 3     3   483 :Export( qw[acme_plurals] );
  3     3   7  
  3         11  
  3         299  
  3         14  
  3         23  
149              
150             sub _init_envariables() {
151              
152 3         26 use Env qw(
153             ASSERT_CONDITIONAL
154             ASSERT_CONDITIONAL_BUILD_POD
155             ASSERT_CONDITIONAL_DEBUG
156             ASSERT_CONDITIONAL_ALLOW_HANDLERS
157 3     3   2470 );
  3         5676  
158              
159 3   50 3   28 $Pod_Generation //= $ASSERT_CONDITIONAL_BUILD_POD || 0;
      33        
160 3   50     103 $Allow_Handlers //= $ASSERT_CONDITIONAL_ALLOW_HANDLERS || 0;
      33        
161 3   50     48 $Assert_Debug //= $ASSERT_CONDITIONAL_DEBUG || 0;
      33        
162              
163 3 50       60 if ($ASSERT_CONDITIONAL) {
164 0         0 for ($ASSERT_CONDITIONAL) {
165 0 0       0 unless (/\b(?: carp | always | never )\b/x) {
166 0         0 warn("Ignoring unknown value '$_' of ASSERT_CONDITIONAL envariable");
167 0         0 next;
168             }
169 0 0 0     0 if ( /\b carp \b/x ) { $Assert_Carp ||= 1 }
  0         0  
170 0 0 0     0 if ( /\b always \b/x ) { $Assert_Always ||= 1 }
  0         0  
171 0 0 0     0 if ( /\b never \b/x ) { $Assert_Never ||= 1 }
  0         0  
172 0 0 0     0 if ( /\b handlers \b/x ) { $Allow_Handlers ||= 1 }
  0         0  
173             }
174             }
175              
176 3 50 50     69 $Assert_Always ||= 1 unless $Assert_Carp || $Assert_Never;
      33        
177              
178 3 50       740 if ($Assert_Never) {
179 0 0       0 warn q(Ignoring $Assert_Always because $Assert_Never is true) if $Assert_Always;
180 0 0       0 warn q(Ignoring $Assert_Carp because $Assert_Never is true) if $Assert_Carp;
181 0         0 $Assert_Always = $Assert_Carp = 0;
182             }
183              
184             }
185              
186             sub _init_public_vars() {
187 3     3   334 Acme::Plural->import();
188             }
189              
190             # Now run that function right now, before the rest of the function:
191 3     3   1847 BEGIN { _init_envariables() }
192              
193             sub botch($)
194             :Export( qw[botch] )
195             {
196 455 50   455 1 2752 return if $Assert_Never;
197              
198 455         1139 my($msg) = @_;
199 455         1065 my $sub = his_assert;
200              
201 455 50       12100 local @SIG{<__{DIE,WARN}__>} unless $Allow_Handlers;
202              
203 455         3470 my $botch = "$0\[$$]: botched assertion $sub: \u$msg";
204              
205 455 50       1199 if ($Assert_Carp) {
206 0         0 Carp::carp($botch)
207             }
208              
209 455 50       1061 if ($Assert_Always) {
210 455         60022 $botch = shortmess("$botch, bailing out");
211 455         89368 Carp::confess("$botch\n Beginning stack dump from failed $sub");
212             }
213 3     3   36 }
  3         10  
  3         18  
214              
215             sub botch_false()
216             :Export( qw[botch] )
217             {
218 0     0 1 0 panic "value should not be false";
219 3     3   439 }
  3         5  
  3         12  
220              
221             sub botch_undef()
222             :Export( qw[botch] )
223             {
224 0     0 1 0 panic "value should not be undef";
225 3     3   442 }
  3         7  
  3         9  
226              
227             #################################################################
228             #
229             # A few stray utility functions that are a bit too intimate with
230             # the assertions in this file to deserve being made public
231              
232             sub botch_argc($$)
233             :Export( qw[botch] )
234             {
235 10     10 1 34 my($have, $want) = @_;
236 10         34 botch_have_thing_wanted(HAVE => $have, THING => "argument", WANTED => $want);
237 3     3   480 }
  3         6  
  3         11  
238              
239             sub botch_array_length($$)
240             :Export( qw[botch] )
241             {
242 11     11 1 44 my($have, $want) = @_;
243 11         60 botch_have_thing_wanted(HAVE => $have, THING => "array element", WANTED => $want);
244 3     3   481 }
  3         7  
  3         21  
245              
246             sub botch_have_thing_wanted(@)
247             :Export( qw[botch] )
248             {
249 21     21 1 116 my(%param) = @_;
250 21   33     81 my $have = $param{HAVE} // botch_undef;
251 21   33     64 my $thing = $param{THING} // botch_undef;
252 21   33     63 my $wanted = $param{WANTED} // botch_undef;
253 21         169 botch "have $N_PLURAL{$thing => $have} but wanted $wanted";
254 3     3   696 }
  3         21  
  3         14  
255              
256             #################################################################
257              
258             sub panic($)
259             :Export( qw[lint botch] )
260             {
261 0     0 1 0 my($msg) = @_;
262 0 0       0 local @SIG{<__{DIE,WARN}__>} unless $Allow_Handlers;
263 0         0 Carp::confess("Panicking on internal error: $msg");
264 3     3   561 }
  3         12  
  3         15  
265              
266             sub FIXME()
267             :Export( qw[lint] )
268             {
269 0     0 1 0 panic "Unimplemented code reached; you forgot to code up a TODO section";
270 3     3   477 }
  3         7  
  3         12  
271              
272             sub NOT_REACHED()
273             :Export( qw[lint] )
274             {
275 0     0 1 0 panic "Logically unreachable code somehow reached";
276 3     3   408 }
  3         6  
  3         10  
277              
278             #################################################################
279              
280             # Find the highest assert_ on the stack so that we don't misreport
281             # failures. For example this next one illustrated below should be
282             # reporting that assert_hash_keys_required botched because that's the
283             # one we called; it shouldn't say that it was assert_min_keys or
284             # assert_hashref_keys_required that botched, even thought the nearest
285             # assert that called botch was actually assert_min_keys.
286              
287             ## perl -Ilib -MAssert::Conditional=:all -e 'assert_hash_keys_required %ENV, "snap"'
288             ## -e[92241]: botched assertion assert_hash_keys_required: Key 'snap' missing from hash, bailing out at -e line 1.
289             ##
290             ## Beginning stack dump from failed assert_hash_keys_required at lib/Assert/Conditional/Utils.pm line 391.
291             ## Assert::Conditional::Utils::botch("key 'snap' missing from hash") called at lib/Assert/Conditional.pm line 1169
292             ## Assert::Conditional::assert_min_keys(REF(0x7fe6196ec3f0), "snap") called at lib/Assert/Conditional.pm line 1135
293             ## Assert::Conditional::assert_hashref_keys_required called at lib/Assert/Conditional.pm line 1104
294             ## Assert::Conditional::assert_hash_keys_required(HASH(0x7fe619028f70), "snap") called at -e line 1
295              
296             # But if we can't find as assert_\w+ on the stack, just use the name of the
297             # the thing that called the thing that called us, so presumably whatever
298             # called botch.
299             sub his_assert()
300             :Export( qw[frame] )
301             {
302 455     455 1 1579 my $assert_rx = qr/::assert_\w+\z/x;
303 455         777 my $i;
304 455         703 my $sub = q();
305 455         2051 for ($i = 1; $sub !~ $assert_rx; $i++) {
306 499   50     1248 $sub = his_sub($i) // last;
307             }
308 455   33     1297 $sub //= his_sub(2); # in case we couldn't find an assert_\w+ sub
309 455   50     961 while ((his_sub($i+1) // "") =~ $assert_rx) {
310 105         305 $sub = his_sub(++$i);
311             }
312 455         2631 $sub =~ s/.*:://;
313 455         1541 return $sub;
314 3     3   974 }
  3         8  
  3         15  
315              
316             sub his_args(;$)
317             :Export( qw[frame] )
318             {
319 59   33 59 1 165 my $frames = @_ && $_[0];
320 59         87 do { package DB; () = caller($frames+2); };
  59         406  
321 59         229 return @DB::args;
322 3     3   590 }
  3         6  
  3         28  
323              
324             sub his_frame(;$)
325             :Export( qw[frame] )
326             {
327 1184   66 1184 1 3222 my $frames = @_ && $_[0];
328 1184         16459 return caller($frames+2);
329 3     3   492 }
  3         7  
  3         12  
330              
331             BEGIN {
332              
333             # Stealing lovely "iota" magic from the
334             # Go language construct of the same name.
335 3     3   21 my $iota;
336 3     3   495 BEGIN { $iota = 0 }
337             use constant {
338 3         864 CALLER_PACKAGE => $iota++,
339             CALLER_FILENAME => $iota++,
340             CALLER_LINE => $iota++,
341             CALLER_SUBROUTINE => $iota++,
342             CALLER_HASARGS => $iota++,
343             CALLER_WANTARRAY => $iota++,
344             CALLER_EVALTEXT => $iota++,
345             CALLER_IS_REQUIRE => $iota++,
346             CALLER_HINTS => $iota++,
347             CALLER_BITMASK => $iota++,
348             CALLER_HINTHASH => $iota++,
349 3     3   22 };
  3         8  
350              
351 3         11 my @caller_consts = qw(
352             CALLER_PACKAGE
353             CALLER_FILENAME
354             CALLER_LINE
355             CALLER_SUBROUTINE
356             CALLER_HASARGS
357             CALLER_WANTARRAY
358             CALLER_EVALTEXT
359             CALLER_IS_REQUIRE
360             CALLER_HINTS
361             CALLER_BITMASK
362             CALLER_HINTHASH
363             );
364              
365 3         8 push @{ $EXPORT_TAGS{CALLER} }, @caller_consts;
  3         13  
366              
367 3         15 push @{ $EXPORT_TAGS{frame} },
368 3         5 @{ $EXPORT_TAGS{CALLER} };
  3         299  
369              
370             }
371              
372             sub his_package(;$)
373             :Export( qw[frame] )
374             {
375 0   0 0 1 0 my $frames = @_ && $_[0];
376 0         0 (his_frame($frames+1))[CALLER_PACKAGE]
377 3     3   23 }
  3         6  
  3         14  
378              
379             sub his_filename(;$)
380             :Export( qw[frame] )
381             {
382 0   0 0 1 0 my $frames = @_ && $_[0];
383 0         0 (his_frame($frames+1))[CALLER_FILENAME]
384 3     3   514 }
  3         7  
  3         12  
385              
386             sub his_line(;$)
387             :Export( qw[frame] )
388             {
389 0   0 0 1 0 my $frames = @_ && $_[0];
390 0         0 (his_frame($frames+1))[CALLER_LINE]
391 3     3   481 }
  3         6  
  3         28  
392              
393             sub his_subroutine(;$)
394             :Export( qw[frame] )
395             {
396 1164   33 1164 1 2787 my $frames = @_ && $_[0];
397 1164         2081 (his_frame($frames+1))[CALLER_SUBROUTINE]
398 3     3   508 }
  3         10  
  3         21  
399              
400             sub his_sub(;$)
401             :Export( qw[frame] )
402             {
403 1164   33 1164 1 3974 my $frames = @_ && $_[0];
404 1164         2141 his_subroutine($frames + 1);
405 3     3   468 }
  3         7  
  3         12  
406              
407             sub his_context(;$)
408             :Export( qw[frame] )
409             {
410 17   33 17 1 62 my $frames = @_ && $_[0];
411 17         55 (his_frame($frames+1))[CALLER_WANTARRAY]
412 3     3   486 }
  3         7  
  3         12  
413              
414             sub his_is_require(;$)
415             :Export( qw[frame] )
416             {
417 3   33 3 1 30 my $frames = @_ && $_[0];
418 3         22 (his_frame($frames+1))[CALLER_IS_REQUIRE]
419 3     3   498 }
  3         7  
  3         13  
420              
421             #################################################################
422              
423             my ($hint_bits, $warning_bits);
424 3     3   1252 BEGIN {($hint_bits, $warning_bits) = ($^H, ${^WARNING_BITS})}
425              
426             sub code_of_coderef($)
427             :Export( qw[code] )
428             {
429 2     2 1 5 my($coderef) = @_;
430              
431 2         191 my $deparse = B::Deparse->new(
432             "-P",
433             "-sC",
434             #"-x9",
435             #"-q",
436             #"-q",
437             );
438 2         9 $deparse->ambient_pragmas(
439             warnings => 'all',
440             strict => 'all',
441             hint_bits => $hint_bits,
442             warning_bits => $warning_bits,
443             ) if 0;
444 2         3858 my $body = $deparse->coderef2text($coderef);
445              
446             #return $body;
447              
448 2         15 for ($body) {
449 2         44 s/^\h+(?:use|no) (?:strict|warnings|feature|integer|utf8|bytes|re)\b[^\n]*\n//gm;
450 2         11 s/^\h+package [^\n]*;\n//gm;
451 2         16 s/\A\{\n\h+([^\n;]*);\n\}\z/{ $1 }/;
452             }
453              
454 2         45 return $body;
455              
456 3     3   49 }
  3         6  
  3         14  
457              
458             sub name_of_coderef($)
459             :Export( qw[code] )
460             {
461 2     2 1 20 require B;
462 2         7 my($coderef) = @_;
463 2         34 my $cv = B::svref_2object($coderef);
464 2 50       74 return unless $cv->isa("B::CV");
465 2         18 my $gv = $cv->GV;
466 2 50       23 return if $gv->isa("B::SPECIAL");
467 2         16 my $subname = $gv->NAME;
468 2         20 my $packname = $gv->STASH->NAME;
469 2         11 return $packname . "::" . $subname;
470 3     3   718 }
  3         41  
  3         15  
471              
472             sub subname_or_code($)
473             :Export( qw[code] )
474             {
475 2     2 1 7 my($coderef) = @_;
476 2         8 my $name = name_of_coderef($coderef);
477 2 50       12 if ($name =~ /__ANON__/) {
478 2         9 return code_of_coderef($coderef);
479             } else {
480 0         0 return "$name()";
481             }
482 3     3   659 }
  3         45  
  3         31  
483              
484             #################################################################
485              
486             sub serialize_conjunction($@) {
487 93     93 0 187 my $conj = shift;
488 93 100       724 (@_ == 0) ? '' :
    100          
    50          
489             (@_ == 1) ? $_[0] :
490             (@_ == 2) ? join(" $conj ", @_) :
491             join(", ", @_[0 .. ($#_-1)], "$conj $_[-1]");
492             }
493              
494             sub commify_series
495             :Export( qw[list] )
496             {
497 0     0 1 0 &commify_and;
498 3     3   764 }
  3         17  
  3         19  
499              
500             sub commify_and
501             :Export( qw[list] )
502             {
503 66     66 0 10141 serialize_conjunction and => @_;
504 3     3   400 }
  3         6  
  3         12  
505              
506             sub commify_or
507             :Export( qw[list] )
508             {
509 27     27 0 6255 serialize_conjunction or => @_;
510 3     3   408 }
  3         6  
  3         12  
511              
512             sub commify_but
513             :Export( qw[list] )
514             {
515 0     0 0 0 serialize_conjunction but => @_;
516 3     3   412 }
  3         6  
  3         13  
517              
518             sub commify_nor
519             :Export( qw[list] )
520             {
521 0     0 0 0 serialize_conjunction nor => @_;
522 3     3   410 }
  3         8  
  3         22  
523              
524             sub quotify_and
525             :Export( qw[list] )
526             {
527 41     41 0 24674 commify_and map { "'$_'" } @_;
  105         287  
528 3     3   466 }
  3         7  
  3         14  
529              
530             sub quotify_or
531             :Export( qw[list] )
532             {
533 16     16 0 6013 commify_or map { "'$_'" } @_;
  26         100  
534 3     3   449 }
  3         7  
  3         53  
535              
536             sub quotify_nor
537             :Export( qw[list] )
538             {
539 0     0 0 0 commify_nor map { "'$_'" } @_;
  0         0  
540 3     3   489 }
  3         7  
  3         17  
541              
542             sub quotify_but
543             :Export( qw[list] )
544             {
545 0     0 0 0 commify_but map { "'$_'" } @_;
  0         0  
546 3     3   463 }
  3         12  
  3         21  
547              
548             sub dump_exports(@)
549             :Export( qw[exports] )
550             {
551 0     0 1 0 my $caller_package = caller;
552 0         0 dump_package_exports($caller_package, @_);
553 3     3   450 }
  3         8  
  3         11  
554              
555             sub dump_package_exports($@)
556             :Export( qw[exports] )
557             {
558 0     0 1 0 my($pkg, @exports) = @_;
559 3     3   413 my %tag2aref = do { no strict 'refs'; %{$pkg . "::EXPORT_TAGS"} };
  3         7  
  3         986  
  0         0  
  0         0  
  0         0  
560 0         0 delete $tag2aref{asserts};
561 0         0 my %seen; # for the all repetition
562 0 0       0 my @taglist = @exports ? @exports : ('all', uca_sort(keys %tag2aref));
563 0         0 my $errors = 0;
564 0 0       0 print "=head2 Export Tags\n\n=over\n\n" if $Pod_Generation;
565 0         0 for my $tag (@taglist) {
566 0 0       0 next if $seen{$tag}++;
567 0         0 my $aref = $tag2aref{$tag};
568 0 0       0 unless ($aref) {
569 0         0 print STDERR ":$tag is not an export tag in $pkg.\n";
570 0         0 $errors++;
571 0         0 next;
572             }
573 0 0       0 if ($Pod_Generation) {
574 0         0 print "=item C<:$tag>\n\n", commify_series(map { "L</$_>" } uca_sort @$aref), ".\n\n";
  0         0  
575             }
576             else {
577 0         0 print "Conditional export tag :$tag exports ", commify_series(uca_sort @$aref), ".\n";
578             }
579             }
580 0 0       0 print "=back\n\n" if $Pod_Generation;
581 0         0 return $errors == 0;
582 3     3   29 }
  3         14  
  3         13  
583              
584             #################################################################
585              
586 3     3   413 sub UCA (_) :Export( qw[unicode] );
  3         6  
  3         13  
587 3     3   378 sub UCA1(_) :Export( qw[unicode] );
  3         11  
  3         22  
588 3     3   362 sub UCA2(_) :Export( qw[unicode] );
  3         7  
  3         14  
589 3     3   361 sub UCA3(_) :Export( qw[unicode] );
  3         8  
  3         11  
590 3     3   369 sub UCA4(_) :Export( qw[unicode] );
  3         6  
  3         10  
591 3     3   369 sub uca_cmp ($$) :Export( qw[unicode] );
  3         7  
  3         15  
592 3     3   383 sub uca1_cmp($$) :Export( qw[unicode] );
  3         7  
  3         11  
593 3     3   368 sub uca2_cmp($$) :Export( qw[unicode] );
  3         5  
  3         20  
594 3     3   374 sub uca3_cmp($$) :Export( qw[unicode] );
  3         8  
  3         24  
595 3     3   386 sub uca4_cmp($$) :Export( qw[unicode] );
  3         7  
  3         13  
596              
597             {
598             my @Comparitor;
599              
600             sub _get_comparitor($) {
601 4     4   14 my($level) = @_;
602 4 50       39 panic "invalid level $level" unless $level =~ /^[1-4]$/;
603 4 50       22 return $Comparitor[$level] if $Comparitor[$level];
604              
605 4         2276 require Unicode::Collate;
606 4         26613 my $class = Unicode::Collate:: ;
607             # need to discount the other ones altogether
608 4         18 my @args = (level => $level); #, variable => "Non-Ignorable");
609             # if ($Opt{locale}) {
610             # require Unicode::Collate::Locale;
611             # $class = Unicode::Collate::Locale:: ;
612             # push @args, locale => $Opt{locale};
613             # }
614 4         151 my $coll = $class->new(@args);
615 4         193342 $Comparitor[$level] = $coll;
616             }
617              
618             for my $strength ( 1 .. 4 ) {
619 3     3   875 no strict "refs";
  3         7  
  3         584  
620             *{ "UCA$strength" } = sub(_) {
621 12     12   2200 state $coll = _get_comparitor($strength);
622 12         45 return $coll->getSortKey($_[0]);
623             };
624              
625             *{ "uca${strength}_cmp" } = sub($$) {
626 0     0   0 my($this, $that) = @_;
627 0         0 "UCA$strength"->($this)
628             cmp
629             "UCA$strength"->($that)
630              
631             };
632             }
633              
634 3     3   24 no warnings "once";
  3         6  
  3         460  
635             *UCA = \&UCA1;
636             *uca_cmp = \&uca1_cmp;
637             }
638              
639             sub uca_sort(@)
640             :Export( qw[unicode list] )
641             {
642 152     152 1 1453469 state $collator = _get_comparitor(4);
643 152         723 return $collator->sort(@_);
644 3     3   22 }
  3         13  
  3         15  
645              
646             {
647             sub _uniq {
648 39     39   50 my %seen;
649             my @out;
650 39 100       58 for (@_) { push @out, $_ unless $seen{$_}++ }
  786         1721  
651 39         211 return @out;
652             }
653              
654             @EXPORT_OK = _uniq(@EXPORT_OK);
655             for my $tag (keys %EXPORT_TAGS) {
656             my @exports = _uniq @{ $EXPORT_TAGS{$tag} };
657             $EXPORT_TAGS{$tag} = [@exports];
658             }
659             }
660              
661             #################################################################
662              
663             { # Private scope for sig mappers
664              
665             our %Config; # constrains in-file lexical visibility
666 3     3   789 use Config;
  3         13  
  3         934  
667              
668             my $sig_count = $Config{sig_size} || botch_undef;
669             my $sig_name_list = $Config{sig_name} || botch_undef;
670             my $sig_num_list = $Config{sig_num} || botch_undef;
671              
672             my @sig_nums = split " ", $sig_num_list;
673             my @sig_names = split " ", $sig_name_list;
674              
675             my $have;
676             $have = @sig_nums;
677             $have == $sig_count || panic "expected $sig_count signums, not $have";
678              
679             $have = @sig_names;
680             $have == $sig_count || panic "expected $sig_count signames, not $have";
681              
682             my(%_Map_num2name, %_Map_name2num);
683              
684             @_Map_num2name {@sig_nums } = @sig_names;
685             @_Map_name2num {@sig_names} = @sig_nums;
686              
687             sub sig_num2name($)
688             :Export( sigmappers )
689             {
690 10     10 1 51 my($num) = @_;
691 10 50       70 $num =~ /^\d+$/ || botch "$num doesn't look like a signal number";
692 10   33     64 return $_Map_num2name{$num} // botch_undef;
693 3     3   25 }
  3         6  
  3         13  
694              
695             sub sig_num2longname($)
696             :Export( sigmappers )
697             {
698 10     10 1 34 return q(SIG) . &sig_num2name;
699 3     3   429 }
  3         8  
  3         12  
700              
701             sub sig_name2num($)
702             :Export( sigmappers )
703             {
704 0     0 1 0 my($name) = @_;
705 2 0   2   339 $name =~ /^\p{upper}+$/ || botch "$name doesn't look like a signal name";
  2         4  
  2         32  
  0         0  
706 0         0 $name =~ s/^SIG//;
707 0   0     0 return $_Map_name2num{$name} // botch_undef;
708 3     3   45289 }
  3         6  
  3         19  
709              
710             }
711              
712             #################################################################
713              
714             # You really don't want to be looking here.
715              
716 0         0 BEGIN {
717             package # so PAUSE doesn't index this
718             Acme::Plural::pl_simple;
719 3     3   861 require Tie::Hash;
720 3         420 our @ISA = qw(Acme::Plural Tie::StdHash);
721              
722             sub TIEHASH {
723 6     6   17 my($class, @args) = @_;
724 6         10 my $self = { };
725 6         13 bless $self, $class;
726 6         269 return $self;
727             }
728              
729             sub FETCH {
730 21     21   41 my($self, $key) = @_;
731 21         334 my($noun, $count) = (split($; => $key), 2);
732 21 100       77 return $noun if $count eq '1';
733 20   66     139 $self->{$noun} ||= $self->_lame_plural($noun);
734             }
735              
736             }
737              
738 0         0 BEGIN {
739             package # so PAUSE doesn't index this
740             Acme::Plural::pl_count;
741 3     3   168 our @ISA = 'Acme::Plural::pl_simple';
742              
743             sub FETCH {
744 21     21   51 my($self, $key) = @_;
745 21         109 my $several = $self->SUPER::FETCH($key);
746 21         166 my($noun, $count) = (split($; => $key), 2);
747 21         133 return "$count $several";
748             }
749              
750             }
751              
752             BEGIN {
753             package # so PAUSE doesn't index this
754             Acme::Plural;
755              
756 3     3   24 use Exporter 'import';
  3         8  
  3         601  
757              
758 3     3   16 our @EXPORT = qw(
759             %PLURAL
760             %N_PLURAL
761             );
762              
763             # TODO: replace with the Lingua::EN::Inflect
764             sub _lame_plural($$) {
765 2     2   22 my($self, $str) = @_;
766 2 50       21 return $str if $str =~ s/(?<! [aeiou] ) y $/ies/x;
767 2 50       29 return $str if $str =~ s/ (?: [szx] | [sc]h ) \K $/es/x;
768 2         18 return $str . "s";
769             }
770              
771 3         14 tie our %PLURAL => "Acme::Plural::pl_simple";
772 3         12 tie our %N_PLURAL => "Acme::Plural::pl_count";
773             }
774              
775             _init_public_vars();
776              
777             1;
778              
779             __END__
780              
781             =encoding utf8
782              
783             =head1 NAME
784              
785             Assert::Conditional::Utils - Utility functions for conditionally-compiled assertions
786              
787             =head1 SYNOPSIS
788              
789             use Assert::Conditional::Utils qw(panic NOT_REACHED);
790              
791             $big > $little
792             || panic("Impossible for $big > $little");
793              
794             chdir("/")
795             || panic("Your root filesystem is corrupt: $!");
796              
797             if ($x) { ... }
798             elsif ($y) { ... }
799             elsif ($z) { ... }
800             else { NOT_REACHED }
801              
802             =head1 DESCRIPTION
803              
804             This module is used by the L<Assert::Conditional> module for most of the
805             non-assert functions it needs. Because this module is still in alpha
806             release, the two examples above should be the only guaranteed serviceable
807             parts.
808              
809             It is possible (but in alpha release, not necessarily advised) to use the
810             C<botch> function to write your own assertions that work like those in
811             L<Assert::Conditional>.
812              
813             The C<panic> function is for internal errors that should never
814             happen. Unlike its cousin C<botch>, it is not controllable through
815             the C<ASSERT_CONDITIONAL> variable.
816              
817             Use C<NOT_REACHED> for some case that can "never" happen.
818              
819             =head2 Exported Variables
820              
821             Here is the list of the support global variables, available for import,
822             which are normally controlled by the C<ASSERT_CONDITIONAL> environment
823             variable.
824              
825             =over
826              
827             =item C<$Assert_Never>
828              
829             Set by default under C<ASSERT_CONDITIONAL=never>.
830              
831             Assertions are never imported, and even if you somehow manage to import
832             them, they will never never make a peep nor raise an exception.
833              
834             =item C<$Assert_Always>
835              
836             Set by default under C<ASSERT_CONDITIONAL=always>.
837              
838             Assertions are always imported, and even if you somehow manage to avoid importing
839             them, they will still raise an exception on error.
840              
841             =item C<$Assert_Carp>
842              
843             Set by default under C<ASSERT_CONDITIONAL=carp>.
844              
845             Assertions are always imported but they do not raise an exception if they fail;
846             instead they all carp at you. This is true even if you manage to call an assertion
847             you haven't imported.
848              
849             =back
850              
851             A few others exist, but you should probably not pay attention to them.
852              
853             =head2 Exported Functions
854              
855             Here is the list of all exported functions with their prototypes:
856              
857             botch ( $ ) ;
858             botch_argc ( $$ ) ;
859             botch_array_length ( $$ ) ;
860             botch_false ( ) ;
861             botch_have_thing_wanted ( @ ) ;
862             botch_undef ( ) ;
863             code_of_coderef ( $ ) ;
864             commify_series ;
865             dump_exports ( @ ) ;
866             dump_package_exports ( $@ ) ;
867             Export ;
868             FIXME ( ) ;
869             his_args ( ;$ ) ;
870             his_assert ( ) ;
871             his_context ( ;$ ) ;
872             his_filename ( ;$ ) ;
873             his_frame ( ;$ ) ;
874             his_is_require ( ;$ ) ;
875             his_line ( ;$ ) ;
876             his_package ( ;$ ) ;
877             his_sub ( ;$ ) ;
878             his_subroutine ( ;$ ) ;
879             name_of_coderef ( $ ) ;
880             NOT_REACHED ( ) ;
881             panic ( $ ) ;
882             sig_name2num ( $ ) ;
883             sig_num2longname ( $ ) ;
884             sig_num2name ( $ ) ;
885             subname_or_code ( $ ) ;
886             UCA ( _ ) ;
887             UCA1 ( _ ) ;
888             uca1_cmp ( $$ ) ;
889             UCA2 ( _ ) ;
890             uca2_cmp ( $$ ) ;
891             UCA3 ( _ ) ;
892             uca3_cmp ( $$ ) ;
893             UCA4 ( _ ) ;
894             uca4_cmp ( $$ ) ;
895             uca_cmp ( $$ ) ;
896             uca_sort ( @ ) ;
897              
898             =for reproduction
899             ASSERT_CONDITIONAL_BUILD_POD=1 perl -Ilib -MAssert::Conditional -e 'Assert::Conditional::Utils->dump_package_exports' | fmt
900              
901             =head2 Export Tags
902              
903             Available exports are grouped by the following tags:
904              
905             =over
906              
907             =item C<:all>
908              
909             L</$Allow_Handlers>, L</$Assert_Always>, L</$Assert_Carp>,
910             L</$Assert_Debug>, L</$Assert_Never>, L</botch>, L</botch_argc>,
911             L</botch_array_length>, L</botch_false>, L</botch_have_thing_wanted>,
912             L</botch_undef>, L</CALLER_BITMASK>, L</CALLER_EVALTEXT>,
913             L</CALLER_FILENAME>, L</CALLER_HASARGS>, L</CALLER_HINTHASH>,
914             L</CALLER_HINTS>, L</CALLER_IS_REQUIRE>, L</CALLER_LINE>,
915             L</CALLER_PACKAGE>, L</CALLER_SUBROUTINE>, L</CALLER_WANTARRAY>,
916             L</code_of_coderef>, L</commify_and>, L</commify_but>, L</commify_nor>,
917             L</commify_or>, L</commify_series>, L</dump_exports>,
918             L</dump_package_exports>, L</FIXME>, L</his_args>, L</his_assert>,
919             L</his_context>, L</his_filename>, L</his_frame>, L</his_is_require>,
920             L</his_line>, L</his_package>, L</his_sub>, L</his_subroutine>,
921             L</name_of_coderef>, L</NOT_REACHED>, L</%N_PLURAL>, L</panic>,
922             L</%PLURAL>, L</quotify_and>, L</quotify_but>, L</quotify_nor>,
923             L</quotify_or>, L</sig_name2num>, L</sig_num2longname>, L</sig_num2name>,
924             L</subname_or_code>, L</UCA>, L</UCA1>, L</uca1_cmp>, L</UCA2>,
925             L</uca2_cmp>, L</UCA3>, L</uca3_cmp>, L</UCA4>, L</uca4_cmp>,
926             L</uca_cmp>, and L</uca_sort>.
927              
928             =item C<:acme_plurals>
929              
930             L</%N_PLURAL> and L</%PLURAL>.
931              
932             =item C<:botch>
933              
934             L</botch>, L</botch_argc>, L</botch_array_length>, L</botch_false>,
935             L</botch_have_thing_wanted>, L</botch_undef>, and L</panic>.
936              
937             =item C<:CALLER>
938              
939             L</CALLER_BITMASK>, L</CALLER_EVALTEXT>, L</CALLER_FILENAME>,
940             L</CALLER_HASARGS>, L</CALLER_HINTHASH>, L</CALLER_HINTS>,
941             L</CALLER_IS_REQUIRE>, L</CALLER_LINE>, L</CALLER_PACKAGE>,
942             L</CALLER_SUBROUTINE>, and L</CALLER_WANTARRAY>.
943              
944             =item C<:code>
945              
946             L</code_of_coderef>, L</name_of_coderef>, and L</subname_or_code>.
947              
948             =item C<:exports>
949              
950             L</dump_exports> and L</dump_package_exports>.
951              
952             =item C<:frame>
953              
954             L</CALLER_BITMASK>, L</CALLER_EVALTEXT>, L</CALLER_FILENAME>,
955             L</CALLER_HASARGS>, L</CALLER_HINTHASH>, L</CALLER_HINTS>,
956             L</CALLER_IS_REQUIRE>, L</CALLER_LINE>, L</CALLER_PACKAGE>,
957             L</CALLER_SUBROUTINE>, L</CALLER_WANTARRAY>, L</his_args>,
958             L</his_assert>, L</his_context>, L</his_filename>, L</his_frame>,
959             L</his_is_require>, L</his_line>, L</his_package>, L</his_sub>, and
960             L</his_subroutine>.
961              
962             =item C<:lint>
963              
964             L</FIXME>, L</NOT_REACHED>, and L</panic>.
965              
966             =item C<:list>
967              
968             L</commify_and>, L</commify_but>, L</commify_nor>, L</commify_or>,
969             L</commify_series>, L</quotify_and>, L</quotify_but>, L</quotify_nor>,
970             L</quotify_or>, and L</uca_sort>.
971              
972             =item C<:sigmappers>
973              
974             L</sig_name2num>, L</sig_num2longname>, and L</sig_num2name>.
975              
976             =item C<:unicode>
977              
978             L</UCA>, L</UCA1>, L</uca1_cmp>, L</UCA2>, L</uca2_cmp>, L</UCA3>,
979             L</uca3_cmp>, L</UCA4>, L</uca4_cmp>, L</uca_cmp>, and L</uca_sort>.
980              
981             =item C<:vars>
982              
983             L</$Allow_Handlers>, L</$Assert_Always>, L</$Assert_Carp>,
984             L</$Assert_Debug>, and L</$Assert_Never>.
985              
986             =back
987              
988             =head2 Exported Functions
989              
990             About the only thing here that's "public" is L</botch>
991             and the C<sig*> name-to-number mapping functions.
992             The rest are internal and shouldn't be relied on.
993              
994             =over
995              
996             =item C<botch($)>
997              
998             The main way that assertions fail. Normally it raises an exception
999             by calling C<Carp::confess>, but this can be controlled using the
1000             C<ASSERT_CONDITIONAL> environment variable or its associated package
1001             variables as previously described.
1002              
1003             We crawl up the stack to find the I<highest> function named C<assert_*> to
1004             use for the message. That way when an assertion calls another assertion and that
1005             second one fails, the reported message uses the name of the first one.
1006              
1007             =item C<botch_false()>
1008              
1009             A way to panic if something is false but shouldn't be.
1010              
1011             =item C<botch_undef()>
1012              
1013             A way to panic if something is undef but shouldn't be.
1014              
1015             =item C<botch_argc($$)>
1016              
1017             =item C<botch_array_length($$)>
1018              
1019             =item C<botch_have_thing_wanted(@)>
1020              
1021             =item C<panic(I<MESSAGE>)>
1022              
1023             This function is used for internal errors that should never happen.
1024             It calls C<Carp::confess> with a prefix indicating that it is an
1025             internal error.
1026              
1027             =item C<FIXME>
1028              
1029             Code you haven't gotten to yet.
1030              
1031             =item C<NOT_REACHED>
1032              
1033             Put this in places that you think you can never reach in your code.
1034              
1035             =item C<his_assert()>
1036              
1037             =item C<his_args(;$)>
1038              
1039             =item C<his_frame(;$)>
1040              
1041             =item C<his_package(;$)>
1042              
1043             =item C<his_filename(;$)>
1044              
1045             =item C<his_line(;$)>
1046              
1047             =item C<his_subroutine(;$)>
1048              
1049             =item C<his_sub(;$)>
1050              
1051             =item C<his_context(;$)>
1052              
1053             =item C<his_is_require(;$)>
1054              
1055             =item C<code_of_coderef(I<CODEREF>)>
1056              
1057             Return the code but not the name of the code reference passed.
1058              
1059             =item C<name_of_coderef(I<CODEREF>)>
1060              
1061             Return the name of the code reference passed.
1062              
1063             =item C<subname_or_code(I<CODEREF>)>
1064              
1065             Return the name of the code reference passed if it is not anonymous;
1066             otherwise return its code.
1067              
1068             =item C<commify_series>
1069              
1070             =item C<dump_exports(@)>
1071              
1072             =item C<dump_package_exports($@)>
1073              
1074             =item C<UCA(_)>
1075              
1076             =item C<UCA1(_)>
1077              
1078             =item C<UCA2(_)>
1079              
1080             =item C<UCA3(_)>
1081              
1082             =item C<UCA4(_)>
1083              
1084             =item C<uca_cmp($$)>
1085              
1086             =item C<uca1_cmp($$)>
1087              
1088             =item C<uca2_cmp($$)>
1089              
1090             =item C<uca3_cmp($$)>
1091              
1092             =item C<uca4_cmp($$)>
1093              
1094             =item C<uca_sort(@)>
1095              
1096             Return its argument list sorted alphabetically.
1097              
1098             =item C<sig_num2name(I<NUMBER>)>
1099              
1100             Returns the name of the signal number, like C<HUP>, C<INT>, etc.
1101              
1102             =item C<sig_num2longname($)>
1103              
1104             Returns the long name of the signal number, like C<SIGHUP>, C<SIGINT>, etc.
1105              
1106             =item sub C<sig_name2num(I<NAME>)>
1107              
1108             Returns the signal number corresponding to the passed in name.
1109              
1110             =back
1111              
1112             =head1 ENVIRONMENT
1113              
1114             The C<ASSERT_CONDITIONAL> variable controls the behavior
1115             of the C<botch> function, and also of the the conditional
1116             importing itself.
1117              
1118             The C<ASSERT_CONDITIONAL_BUILD_POD> variable is used internally.
1119              
1120             =head1 SEE ALSO
1121              
1122             The L<Assert::Conditional> module that uses these utilities
1123             and
1124             the L<Exporter::ConditionalSubs> module which that module is based on.
1125              
1126             =head1 BUGS AND LIMITATIONS
1127              
1128             Probably many. This is an beta release.
1129              
1130             =head1 AUTHOR
1131              
1132             Tom Christiansen C<< <tchrist@perl.com> >>
1133              
1134             =head1 LICENCE AND COPYRIGHT
1135              
1136             Copyright (c) 2015-2018 Tom Christiansen C<< <tchrist@perl.com> >>.
1137             All Rights Reserved.
1138              
1139             This module is free software; you can redistribute it and/or
1140             modify it under the same terms as Perl itself. See L<perlartistic>.