123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450 |
- package constant;
- use 5.008;
- use strict;
- use warnings::register;
- our $VERSION = '1.33';
- our %declared;
- my %keywords = map +($_, 1), qw{ BEGIN INIT CHECK END DESTROY AUTOLOAD };
- $keywords{UNITCHECK}++ if $] > 5.009;
- my %forced_into_main = map +($_, 1),
- qw{ STDIN STDOUT STDERR ARGV ARGVOUT ENV INC SIG };
- my %forbidden = (%keywords, %forced_into_main);
- my $normal_constant_name = qr/^_?[^\W_0-9]\w*\z/;
- my $tolerable = qr/^[A-Za-z_]\w*\z/;
- my $boolean = qr/^[01]?\z/;
- BEGIN {
-
-
-
-
- my $const = $] > 5.009002;
- my $downgrade = $] < 5.015004;
- my $constarray = exists &_make_const;
- if ($const) {
- Internals::SvREADONLY($const, 1);
- Internals::SvREADONLY($downgrade, 1);
- $constant::{_CAN_PCS} = \$const;
- $constant::{_DOWNGRADE} = \$downgrade;
- $constant::{_CAN_PCS_FOR_ARRAY} = \$constarray;
- }
- else {
- no strict 'refs';
- *{"_CAN_PCS"} = sub () {$const};
- *{"_DOWNGRADE"} = sub () { $downgrade };
- *{"_CAN_PCS_FOR_ARRAY"} = sub () { $constarray };
- }
- }
- sub import {
- my $class = shift;
- return unless @_;
- my $constants;
- my $multiple = ref $_[0];
- my $caller = caller;
- my $flush_mro;
- my $symtab;
- if (_CAN_PCS) {
- no strict 'refs';
- $symtab = \%{$caller . '::'};
- };
- if ( $multiple ) {
- if (ref $_[0] ne 'HASH') {
- require Carp;
- Carp::croak("Invalid reference type '".ref(shift)."' not 'HASH'");
- }
- $constants = shift;
- } else {
- unless (defined $_[0]) {
- require Carp;
- Carp::croak("Can't use undef as constant name");
- }
- $constants->{+shift} = undef;
- }
- foreach my $name ( keys %$constants ) {
- my $pkg;
- my $symtab = $symtab;
- my $orig_name = $name;
- if ($name =~ s/(.*)(?:::|')(?=.)//s) {
- $pkg = $1;
- if (_CAN_PCS && $pkg ne $caller) {
- no strict 'refs';
- $symtab = \%{$pkg . '::'};
- }
- }
- else {
- $pkg = $caller;
- }
-
- if ($name =~ $normal_constant_name and !$forbidden{$name}) {
-
-
- } elsif ($forced_into_main{$name} and $pkg ne 'main') {
- require Carp;
- Carp::croak("Constant name '$name' is forced into main::");
-
- } elsif ($name =~ /^__/) {
- require Carp;
- Carp::croak("Constant name '$name' begins with '__'");
-
- } elsif ($name =~ $tolerable) {
-
- if (warnings::enabled()) {
- if ($keywords{$name}) {
- warnings::warn("Constant name '$name' is a Perl keyword");
- } elsif ($forced_into_main{$name}) {
- warnings::warn("Constant name '$name' is " .
- "forced into package main::");
- }
- }
-
-
- } elsif ($name =~ $boolean) {
- require Carp;
- if (@_) {
- Carp::croak("Constant name '$name' is invalid");
- } else {
- Carp::croak("Constant name looks like boolean value");
- }
- } else {
-
- require Carp;
- Carp::croak("Constant name '$name' has invalid characters");
- }
- {
- no strict 'refs';
- my $full_name = "${pkg}::$name";
- $declared{$full_name}++;
- if ($multiple || @_ == 1) {
- my $scalar = $multiple ? $constants->{$orig_name} : $_[0];
- if (_DOWNGRADE) {
-
-
-
- utf8::is_utf8 $name and utf8::encode $name;
- }
-
-
- if (_CAN_PCS) {
-
-
-
-
-
-
-
- Internals::SvREADONLY($scalar, 1);
- if (!exists $symtab->{$name}) {
- $symtab->{$name} = \$scalar;
- ++$flush_mro->{$pkg};
- }
- else {
- local $constant::{_dummy} = \$scalar;
- *$full_name = \&{"_dummy"};
- }
- } else {
- *$full_name = sub () { $scalar };
- }
- } elsif (@_) {
- my @list = @_;
- if (_CAN_PCS_FOR_ARRAY) {
- _make_const($list[$_]) for 0..$#list;
- _make_const(@list);
- if (!exists $symtab->{$name}) {
- $symtab->{$name} = \@list;
- $flush_mro->{$pkg}++;
- }
- else {
- local $constant::{_dummy} = \@list;
- *$full_name = \&{"_dummy"};
- }
- }
- else { *$full_name = sub () { @list }; }
- } else {
- *$full_name = sub () { };
- }
- }
- }
-
- if (_CAN_PCS && $flush_mro) {
- mro::method_changed_in($_) for keys %$flush_mro;
- }
- }
- 1;
- __END__
|