File Coverage

blib/lib/constant.pm
Criterion Covered Total %
statement 0 51 0.0
branch 0 36 0.0
condition 0 12 0.0
subroutine 0 4 0.0
pod n/a
total 0 103 0.0


line stmt bran cond sub pod time code
1             package constant;
2             use 5.008;
3             use strict;
4             use warnings::register;
5              
6             use vars qw($VERSION %declared);
7             $VERSION = '1.27';
8              
9             #=======================================================================
10              
11             # Some names are evil choices.
12             my %keywords = map +($_, 1), qw{ BEGIN INIT CHECK END DESTROY AUTOLOAD };
13             $keywords{UNITCHECK}++ if $] > 5.009;
14              
15             my %forced_into_main = map +($_, 1),
16             qw{ STDIN STDOUT STDERR ARGV ARGVOUT ENV INC SIG };
17              
18             my %forbidden = (%keywords, %forced_into_main);
19              
20             my $normal_constant_name = qr/^_?[^\W_0-9]\w*\z/;
21             my $tolerable = qr/^[A-Za-z_]\w*\z/;
22             my $boolean = qr/^[01]?\z/;
23              
24             BEGIN {
25             # We'd like to do use constant _CAN_PCS => $] > 5.009002
26             # but that's a bit tricky before we load the constant module :-)
27             # By doing this, we save 1 run time check for *every* call to import.
28             no strict 'refs';
29             my $const = $] > 5.009002;
30             *_CAN_PCS = sub () {$const};
31              
32             my $downgrade = $] < 5.015004; # && $] >= 5.008
33             *_DOWNGRADE = sub () { $downgrade };
34             }
35              
36             #=======================================================================
37             # import() - import symbols into user's namespace
38             #
39             # What we actually do is define a function in the caller's namespace
40             # which returns the value. The function we create will normally
41             # be inlined as a constant, thereby avoiding further sub calling
42             # overhead.
43             #=======================================================================
44             sub import {
45 0     0     my $class = shift;
46 0 0         return unless @_; # Ignore 'use constant;'
47 0           my $constants;
48 0           my $multiple = ref $_[0];
49 0           my $pkg = caller;
50 0           my $flush_mro;
51             my $symtab;
52              
53 0           if (_CAN_PCS) {
54             no strict 'refs';
55 0           $symtab = \%{$pkg . '::'};
  0            
56             };
57              
58 0 0         if ( $multiple ) {
59 0 0         if (ref $_[0] ne 'HASH') {
60 0           require Carp;
61 0           Carp::croak("Invalid reference type '".ref(shift)."' not 'HASH'");
62             }
63 0           $constants = shift;
64             } else {
65 0 0         unless (defined $_[0]) {
66 0           require Carp;
67 0           Carp::croak("Can't use undef as constant name");
68             }
69 0           $constants->{+shift} = undef;
70             }
71              
72 0           foreach my $name ( keys %$constants ) {
73             # Normal constant name
74 0 0 0       if ($name =~ $normal_constant_name and !$forbidden{$name}) {
    0 0        
    0          
    0          
    0          
75             # Everything is okay
76              
77             # Name forced into main, but we're not in main. Fatal.
78             } elsif ($forced_into_main{$name} and $pkg ne 'main') {
79 0           require Carp;
80 0           Carp::croak("Constant name '$name' is forced into main::");
81              
82             # Starts with double underscore. Fatal.
83             } elsif ($name =~ /^__/) {
84 0           require Carp;
85 0           Carp::croak("Constant name '$name' begins with '__'");
86              
87             # Maybe the name is tolerable
88             } elsif ($name =~ $tolerable) {
89             # Then we'll warn only if you've asked for warnings
90 0 0         if (warnings::enabled()) {
91 0 0         if ($keywords{$name}) {
    0          
92 0           warnings::warn("Constant name '$name' is a Perl keyword");
93             } elsif ($forced_into_main{$name}) {
94 0           warnings::warn("Constant name '$name' is " .
95             "forced into package main::");
96             }
97             }
98              
99             # Looks like a boolean
100             # use constant FRED == fred;
101             } elsif ($name =~ $boolean) {
102 0           require Carp;
103 0 0         if (@_) {
104 0           Carp::croak("Constant name '$name' is invalid");
105             } else {
106 0           Carp::croak("Constant name looks like boolean value");
107             }
108              
109             } else {
110             # Must have bad characters
111 0           require Carp;
112 0           Carp::croak("Constant name '$name' has invalid characters");
113             }
114              
115             {
116 0           no strict 'refs';
117 0           my $full_name = "${pkg}::$name";
118 0           $declared{$full_name}++;
119 0 0 0       if ($multiple || @_ == 1) {
    0          
120 0 0         my $scalar = $multiple ? $constants->{$name} : $_[0];
121              
122             if (_DOWNGRADE) { # for 5.8 to 5.14
123             # Work around perl bug #31991: Sub names (actually glob
124             # names in general) ignore the UTF8 flag. So we have to
125             # turn it off to get the "right" symbol table entry.
126             utf8::is_utf8 $name and utf8::encode $name;
127             }
128              
129             # The constant serves to optimise this entire block out on
130             # 5.8 and earlier.
131 0 0 0       if (_CAN_PCS && $symtab && !exists $symtab->{$name}) {
132             # No typeglob yet, so we can use a reference as space-
133             # efficient proxy for a constant subroutine
134             # The check in Perl_ck_rvconst knows that inlinable
135             # constants from cv_const_sv are read only. So we have to:
136 0           Internals::SvREADONLY($scalar, 1);
137 0           $symtab->{$name} = \$scalar;
138 0           ++$flush_mro;
139             } else {
140 0     0     *$full_name = sub () { $scalar };
  0            
141             }
142             } elsif (@_) {
143 0           my @list = @_;
144 0     0     *$full_name = sub () { @list };
  0            
145             } else {
146 0     0     *$full_name = sub () { };
  0            
147             }
148             }
149             }
150             # Flush the cache exactly once if we make any direct symbol table changes.
151 0 0         mro::method_changed_in($pkg) if _CAN_PCS && $flush_mro;
152             }
153              
154             1;
155              
156             __END__