File Coverage

blib/lib/AnyDBM_File/Importer.pm
Criterion Covered Total %
statement 21 77 27.2
branch 1 44 2.2
condition 0 24 0.0
subroutine 6 6 100.0
pod n/a
total 28 151 18.5


line stmt bran cond sub pod time code
1             #$Id$
2             package AnyDBM_File::Importer;
3 1     1   34312 use strict;
  1         2  
  1         30  
4 1     1   6 use warnings;
  1         2  
  1         69  
5             our $VERSION = '0.012';
6              
7             =head1 AnyDBM_File::Importer - Import DBM package symbols when using AnyDBM_File
8              
9             =head1 SYNOPSIS
10              
11             BEGIN {
12             @AnyDBM_File::ISA = qw( DB_File SDBM_File ) unless @AnyDBM_File::ISA;
13             }
14             use AnyDBM_File;
15             use vars qw( $DB_BTREE &R_DUP); # must declare the globals you expect to use
16             use AnyDBM_File::Importer qw(:bdb); # an import tag is REQUIRED
17              
18             my %db;
19             $DB_BTREE->{'flags'} = R_DUP;
20             tie( %db, 'AnyDBM_File', O_CREAT | O_RDWR, 0644, $DB_BTREE);
21              
22             =head1 DESCRIPTION
23              
24             This module allows symbols (like $DB_HASH, R_DUP, etc.) to be
25             imported into the caller's namespace when using the L DBM
26             auto-selection package. L includes its auto-selected module
27             by using C, which unlike C does not export symbols in
28             the required packages C<@EXPORT> array.
29              
30             This is essentially a hack because it relies on L
31             internal behavior. Specifically, at the time of DBM module selection,
32             C sets its C<@ISA> to a length 1 array containing the
33             package name of the selected DBM module.
34              
35             =head1 USAGE NOTES
36              
37             Use of L within module code currently requires
38             a kludge. Symbols of imported variables or constants need to be
39             declared globals, as in the SYNOPSIS above. This is not necessary when
40             L is used in package main. Better solutions are hereby solicited with advance gratitude.
41              
42             L consists entirely of an import function. To
43             import the symbols, a tag must be given. More than one tag can be
44             supplied. Symbols cannot be individually specified at the moment.
45              
46             :bdb DB_File (BDB) symbols ($DB_*, R_*, O_*)
47             :db $DB_* type hashrefs
48             :R R_* constants (R_DUP, R_FIRST, etc)
49             :O O_* constants (O_CREAT, O_RDWR, etc)
50             :other Exportable symbols not in any of the above groups
51             :all All exportable symbols
52              
53             Exportable symbols to be completely ignored can be added to
54             C<@AnyDBM_File::Importer::IGNORED_SYMBOLS>. By default, this list
55             includes the following GNU-undefined symbols:
56            
57             R_NOKEY, R_SNAPSHOT
58             O_ALIAS, O_ASYNC, O_DEFER, O_DIRECTORY, O_EXLOCK, O_LARGEFILE
59             O_RANDOM, O_RAW, O_RSRC, O_SEQUENTIAL, O_SHLOCK, O_TEMPORARY
60            
61            
62             =head1 AUTHOR - Mark A. Jensen
63              
64             Email: maj -at- fortinbras -dot- us
65             http://fortinbras.us
66             http://www.bioperl.org/wiki/Mark_Jensen
67              
68             =head1 COPYRIGHT
69              
70             This program is free software; you can redistribute
71             it and/or modify it under the same terms as Perl itself.
72              
73             The full text of the license can be found in the
74             LICENSE file included with this module.
75              
76             =cut
77              
78 1     1   5 use constant { R_CONST => 1, O_CONST => 2, DB_TYPES => 4, OTHER => 8 };
  1         6  
  1         86  
79              
80             # ignore "Prototype mismatch:... none vs. ()"
81             # and "Amibiguous use of ... resolved to ..." warnings
82             # for now.../maj
83              
84 1     1   5 no warnings qw(prototype ambiguous);
  1         1  
  1         33  
85              
86 1     1   4 use Carp;
  1         2  
  1         1183  
87              
88             # symbols to ignore; default are gnu-undefined symbols
89             our @IGNORED_SYMBOLS = qw(R_NOKEY R_SNAPSHOT O_ALIAS O_ASYNC O_DEFER O_DIRECTORY O_EXLOCK O_LARGEFILE O_RANDOM O_RAW O_RSRC O_SEQUENTIAL O_SHLOCK O_TEMPORARY );
90              
91             sub import {
92 1     1   8 my ($class, @args) = @_;
93 1         3 my ($pkg, $fn, $ln) = caller;
94 1         17 my $flags = 0;
95 1         3 for (@args) {
96 1 50       5 !defined($_) && do {
97             # simple use
98 1         13 return 1;
99             };
100 0 0         /^:all$/ && do {
101 0           $flags |= (R_CONST | O_CONST | DB_TYPES | OTHER );
102 0           next;
103             };
104 0 0         /^:other$/ && do {
105 0           $flags |= OTHER;
106 0           next;
107             };
108 0 0         /^:bdb/ && do {
109 0           $flags |= (R_CONST | O_CONST | DB_TYPES );
110 0           next;
111             };
112 0 0         /^:db$/ && do {
113 0           $flags |= DB_TYPES;
114 0           next;
115             };
116 0 0         /^:R$/ && do {
117 0           $flags |= R_CONST;
118 0           next;
119             };
120 0 0         /^:O$/ && do {
121 0           $flags |= O_CONST;
122 0           next;
123             };
124 0           do {
125 0           croak "Tag '$_' not recognized";
126             };
127             }
128 0 0         unless ($flags) {
129 0           carp __PACKAGE__.": No symbols exported";
130 0           return;
131             }
132            
133 0 0         if (!@AnyDBM_File::ISA) {
    0          
134 0           croak "No packages specified for AnyDBM_File (have you forgotten to include AnyDBM_File?)"
135             }
136             elsif (@AnyDBM_File::ISA > 1) {
137 0           carp "AnyDBM_File has not yet selected a single DBM package; returning..."
138             }
139             else {
140 0           my @export = eval "(\@$AnyDBM_File::ISA[0]::EXPORT, \@$AnyDBM_File::ISA[0]::EXPORT_OK)";
141 0           my $ref;
142 0           for (@export) {
143             # kludge: ignore gnu perl undefined symbols
144 0           my $qm = quotemeta;
145 0 0         next if grep(/^$qm$/, @IGNORED_SYMBOLS);
146 0 0         m/^\$(.*)/ && do {
147 0           $_ = substr $_, 1;
148 0           eval "\$ref = *${pkg}::$_\{SCALAR}";
149 0 0         croak $@ if $@;
150 0 0 0       if ( ($flags & DB_TYPES and ($1 =~ /^DB_/)) ||
      0        
      0        
151             ($flags & OTHER and ($1 !~ /^DB_/)) ) {
152 0           $$ref = eval "\$$AnyDBM_File::ISA[0]\::$_";
153             }
154 0           next;
155             };
156 0 0         m/^\@(.*)/ && do {
157 0           $_ = substr $_, 1;
158 0           eval "\$ref = *${pkg}::$_\{ARRAY}";
159 0 0         croak $@ if $@;
160 0 0         if ($flags & OTHER) {
161 0           $$ref = eval "\@$AnyDBM_File::ISA[0]\::$1";
162             }
163 0           next;
164             };
165 0 0         m/^\%(.*)/ && do {
166 0           $_ = substr $_, 1;
167 0           eval "\$ref = *${pkg}::$_\{HASH}";
168 0 0         croak $@ if $@;
169 0 0         if ($flags & OTHER) {
170 0           $$ref = eval "\%$AnyDBM_File::ISA[0]\::$1";
171             }
172 0           next;
173             };
174 0 0         m/^[^\$@%]/ && do {
175 0 0 0       eval "*{${pkg}::$_} = \\\&$AnyDBM_File::ISA[0]\::$_" if
      0        
      0        
      0        
      0        
176             ( ($flags & R_CONST and /^R_/) ||
177             ($flags & O_CONST and /^O_/) ||
178             ($flags & OTHER and /^[RO]_/) );
179              
180 0           next;
181             };
182             }
183 0           return 1;
184             }
185             }
186              
187             1;