File Coverage

blib/lib/constant.pm
Criterion Covered Total %
statement 0 72 0.0
branch 0 42 0.0
condition 0 9 0.0
subroutine 0 4 0.0
pod n/a
total 0 127 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             our $VERSION = '1.33';
7             our %declared;
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 several run time checks for *every* call
28             # to import.
29             my $const = $] > 5.009002;
30             my $downgrade = $] < 5.015004; # && $] >= 5.008
31             my $constarray = exists &_make_const;
32             if ($const) {
33             Internals::SvREADONLY($const, 1);
34             Internals::SvREADONLY($downgrade, 1);
35             $constant::{_CAN_PCS} = \$const;
36             $constant::{_DOWNGRADE} = \$downgrade;
37             $constant::{_CAN_PCS_FOR_ARRAY} = \$constarray;
38             }
39             else {
40             no strict 'refs';
41             *{"_CAN_PCS"} = sub () {$const};
42             *{"_DOWNGRADE"} = sub () { $downgrade };
43             *{"_CAN_PCS_FOR_ARRAY"} = sub () { $constarray };
44             }
45             }
46              
47             #=======================================================================
48             # import() - import symbols into user's namespace
49             #
50             # What we actually do is define a function in the caller's namespace
51             # which returns the value. The function we create will normally
52             # be inlined as a constant, thereby avoiding further sub calling
53             # overhead.
54             #=======================================================================
55             sub import {
56 0     0     my $class = shift;
57 0 0         return unless @_; # Ignore 'use constant;'
58 0           my $constants;
59 0           my $multiple = ref $_[0];
60 0           my $caller = caller;
61 0           my $flush_mro;
62             my $symtab;
63              
64 0           if (_CAN_PCS) {
65             no strict 'refs';
66 0           $symtab = \%{$caller . '::'};
  0            
67             };
68              
69 0 0         if ( $multiple ) {
70 0 0         if (ref $_[0] ne 'HASH') {
71 0           require Carp;
72 0           Carp::croak("Invalid reference type '".ref(shift)."' not 'HASH'");
73             }
74 0           $constants = shift;
75             } else {
76 0 0         unless (defined $_[0]) {
77 0           require Carp;
78 0           Carp::croak("Can't use undef as constant name");
79             }
80 0           $constants->{+shift} = undef;
81             }
82              
83 0           foreach my $name ( keys %$constants ) {
84 0           my $pkg;
85 0           my $symtab = $symtab;
86 0           my $orig_name = $name;
87 0 0         if ($name =~ s/(.*)(?:::|')(?=.)//s) {
88 0           $pkg = $1;
89 0 0         if (_CAN_PCS && $pkg ne $caller) {
90             no strict 'refs';
91 0           $symtab = \%{$pkg . '::'};
  0            
92             }
93             }
94             else {
95 0           $pkg = $caller;
96             }
97              
98             # Normal constant name
99 0 0 0       if ($name =~ $normal_constant_name and !$forbidden{$name}) {
    0 0        
    0          
    0          
    0          
100             # Everything is okay
101              
102             # Name forced into main, but we're not in main. Fatal.
103             } elsif ($forced_into_main{$name} and $pkg ne 'main') {
104 0           require Carp;
105 0           Carp::croak("Constant name '$name' is forced into main::");
106              
107             # Starts with double underscore. Fatal.
108             } elsif ($name =~ /^__/) {
109 0           require Carp;
110 0           Carp::croak("Constant name '$name' begins with '__'");
111              
112             # Maybe the name is tolerable
113             } elsif ($name =~ $tolerable) {
114             # Then we'll warn only if you've asked for warnings
115 0 0         if (warnings::enabled()) {
116 0 0         if ($keywords{$name}) {
    0          
117 0           warnings::warn("Constant name '$name' is a Perl keyword");
118             } elsif ($forced_into_main{$name}) {
119 0           warnings::warn("Constant name '$name' is " .
120             "forced into package main::");
121             }
122             }
123              
124             # Looks like a boolean
125             # use constant FRED == fred;
126             } elsif ($name =~ $boolean) {
127 0           require Carp;
128 0 0         if (@_) {
129 0           Carp::croak("Constant name '$name' is invalid");
130             } else {
131 0           Carp::croak("Constant name looks like boolean value");
132             }
133              
134             } else {
135             # Must have bad characters
136 0           require Carp;
137 0           Carp::croak("Constant name '$name' has invalid characters");
138             }
139              
140             {
141 0           no strict 'refs';
142 0           my $full_name = "${pkg}::$name";
143 0           $declared{$full_name}++;
144 0 0 0       if ($multiple || @_ == 1) {
    0          
145 0 0         my $scalar = $multiple ? $constants->{$orig_name} : $_[0];
146              
147             if (_DOWNGRADE) { # for 5.8 to 5.14
148             # Work around perl bug #31991: Sub names (actually glob
149             # names in general) ignore the UTF8 flag. So we have to
150             # turn it off to get the "right" symbol table entry.
151             utf8::is_utf8 $name and utf8::encode $name;
152             }
153              
154             # The constant serves to optimise this entire block out on
155             # 5.8 and earlier.
156 0           if (_CAN_PCS) {
157             # Use a reference as a proxy for a constant subroutine.
158             # If this is not a glob yet, it saves space. If it is
159             # a glob, we must still create it this way to get the
160             # right internal flags set, as constants are distinct
161             # from subroutines created with sub(){...}.
162             # The check in Perl_ck_rvconst knows that inlinable
163             # constants from cv_const_sv are read only. So we have to:
164 0           Internals::SvREADONLY($scalar, 1);
165 0 0         if (!exists $symtab->{$name}) {
166 0           $symtab->{$name} = \$scalar;
167 0           ++$flush_mro->{$pkg};
168             }
169             else {
170 0           local $constant::{_dummy} = \$scalar;
171 0           *$full_name = \&{"_dummy"};
  0            
172             }
173             } else {
174 0     0     *$full_name = sub () { $scalar };
175             }
176             } elsif (@_) {
177 0           my @list = @_;
178 0           if (_CAN_PCS_FOR_ARRAY) {
179 0           _make_const($list[$_]) for 0..$#list;
180 0           _make_const(@list);
181 0 0         if (!exists $symtab->{$name}) {
182 0           $symtab->{$name} = \@list;
183 0           $flush_mro->{$pkg}++;
184             }
185             else {
186 0           local $constant::{_dummy} = \@list;
187 0           *$full_name = \&{"_dummy"};
  0            
188             }
189             }
190 0     0     else { *$full_name = sub () { @list }; }
191             } else {
192 0     0     *$full_name = sub () { };
  0            
193             }
194             }
195             }
196             # Flush the cache exactly once if we make any direct symbol table changes.
197 0 0         if (_CAN_PCS && $flush_mro) {
198 0           mro::method_changed_in($_) for keys %$flush_mro;
199             }
200             }
201              
202             1;
203              
204             __END__