ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/staticperl/perl/warnings.pl
Revision: 1.1
Committed: Thu Jun 30 14:26:43 2005 UTC (19 years ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: PERL-5-8-7, HEAD
Branch point for: PERL
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 #!/usr/bin/perl
2    
3     $VERSION = '1.02';
4    
5     BEGIN {
6     push @INC, './lib';
7     }
8     use strict ;
9    
10     sub DEFAULT_ON () { 1 }
11     sub DEFAULT_OFF () { 2 }
12    
13     my $tree = {
14    
15     'all' => [ 5.008, {
16     'io' => [ 5.008, {
17     'pipe' => [ 5.008, DEFAULT_OFF],
18     'unopened' => [ 5.008, DEFAULT_OFF],
19     'closed' => [ 5.008, DEFAULT_OFF],
20     'newline' => [ 5.008, DEFAULT_OFF],
21     'exec' => [ 5.008, DEFAULT_OFF],
22     'layer' => [ 5.008, DEFAULT_OFF],
23     }],
24     'syntax' => [ 5.008, {
25     'ambiguous' => [ 5.008, DEFAULT_OFF],
26     'semicolon' => [ 5.008, DEFAULT_OFF],
27     'precedence' => [ 5.008, DEFAULT_OFF],
28     'bareword' => [ 5.008, DEFAULT_OFF],
29     'reserved' => [ 5.008, DEFAULT_OFF],
30     'digit' => [ 5.008, DEFAULT_OFF],
31     'parenthesis' => [ 5.008, DEFAULT_OFF],
32     'printf' => [ 5.008, DEFAULT_OFF],
33     'prototype' => [ 5.008, DEFAULT_OFF],
34     'qw' => [ 5.008, DEFAULT_OFF],
35     }],
36     'severe' => [ 5.008, {
37     'inplace' => [ 5.008, DEFAULT_ON],
38     'internal' => [ 5.008, DEFAULT_ON],
39     'debugging' => [ 5.008, DEFAULT_ON],
40     'malloc' => [ 5.008, DEFAULT_ON],
41     }],
42     'deprecated' => [ 5.008, DEFAULT_OFF],
43     'void' => [ 5.008, DEFAULT_OFF],
44     'recursion' => [ 5.008, DEFAULT_OFF],
45     'redefine' => [ 5.008, DEFAULT_OFF],
46     'numeric' => [ 5.008, DEFAULT_OFF],
47     'uninitialized' => [ 5.008, DEFAULT_OFF],
48     'once' => [ 5.008, DEFAULT_OFF],
49     'misc' => [ 5.008, DEFAULT_OFF],
50     'regexp' => [ 5.008, DEFAULT_OFF],
51     'glob' => [ 5.008, DEFAULT_OFF],
52     'y2k' => [ 5.008, DEFAULT_OFF],
53     'untie' => [ 5.008, DEFAULT_OFF],
54     'substr' => [ 5.008, DEFAULT_OFF],
55     'taint' => [ 5.008, DEFAULT_OFF],
56     'signal' => [ 5.008, DEFAULT_OFF],
57     'closure' => [ 5.008, DEFAULT_OFF],
58     'overflow' => [ 5.008, DEFAULT_OFF],
59     'portable' => [ 5.008, DEFAULT_OFF],
60     'utf8' => [ 5.008, DEFAULT_OFF],
61     'exiting' => [ 5.008, DEFAULT_OFF],
62     'pack' => [ 5.008, DEFAULT_OFF],
63     'unpack' => [ 5.008, DEFAULT_OFF],
64     'threads' => [ 5.008, DEFAULT_OFF],
65     #'default' => [ 5.008, DEFAULT_ON ],
66     }],
67     } ;
68    
69     ###########################################################################
70     sub tab {
71     my($l, $t) = @_;
72     $t .= "\t" x ($l - (length($t) + 1) / 8);
73     $t;
74     }
75    
76     ###########################################################################
77    
78     my %list ;
79     my %Value ;
80     my %ValueToName ;
81     my %NameToValue ;
82     my $index ;
83    
84     my %v_list = () ;
85    
86     sub valueWalk
87     {
88     my $tre = shift ;
89     my @list = () ;
90     my ($k, $v) ;
91    
92     foreach $k (sort keys %$tre) {
93     $v = $tre->{$k};
94     die "duplicate key $k\n" if defined $list{$k} ;
95     die "Value associated with key '$k' is not an ARRAY reference"
96     if !ref $v || ref $v ne 'ARRAY' ;
97    
98     my ($ver, $rest) = @{ $v } ;
99     push @{ $v_list{$ver} }, $k;
100    
101     if (ref $rest)
102     { valueWalk ($rest) }
103    
104     }
105    
106     }
107    
108     sub orderValues
109     {
110     my $index = 0;
111     foreach my $ver ( sort { $a <=> $b } keys %v_list ) {
112     foreach my $name (@{ $v_list{$ver} } ) {
113     $ValueToName{ $index } = [ uc $name, $ver ] ;
114     $NameToValue{ uc $name } = $index ++ ;
115     }
116     }
117    
118     return $index ;
119     }
120    
121     ###########################################################################
122    
123     sub walk
124     {
125     my $tre = shift ;
126     my @list = () ;
127     my ($k, $v) ;
128    
129     foreach $k (sort keys %$tre) {
130     $v = $tre->{$k};
131     die "duplicate key $k\n" if defined $list{$k} ;
132     #$Value{$index} = uc $k ;
133     die "Can't find key '$k'"
134     if ! defined $NameToValue{uc $k} ;
135     push @{ $list{$k} }, $NameToValue{uc $k} ;
136     die "Value associated with key '$k' is not an ARRAY reference"
137     if !ref $v || ref $v ne 'ARRAY' ;
138    
139     my ($ver, $rest) = @{ $v } ;
140     if (ref $rest)
141     { push (@{ $list{$k} }, walk ($rest)) }
142    
143     push @list, @{ $list{$k} } ;
144     }
145    
146     return @list ;
147     }
148    
149     ###########################################################################
150    
151     sub mkRange
152     {
153     my @a = @_ ;
154     my @out = @a ;
155     my $i ;
156    
157    
158     for ($i = 1 ; $i < @a; ++ $i) {
159     $out[$i] = ".."
160     if $a[$i] == $a[$i - 1] + 1 && $a[$i] + 1 == $a[$i + 1] ;
161     }
162    
163     my $out = join(",",@out);
164    
165     $out =~ s/,(\.\.,)+/../g ;
166     return $out;
167     }
168    
169     ###########################################################################
170     sub printTree
171     {
172     my $tre = shift ;
173     my $prefix = shift ;
174     my ($k, $v) ;
175    
176     my $max = (sort {$a <=> $b} map { length $_ } keys %$tre)[-1] ;
177     my @keys = sort keys %$tre ;
178    
179     while ($k = shift @keys) {
180     $v = $tre->{$k};
181     die "Value associated with key '$k' is not an ARRAY reference"
182     if !ref $v || ref $v ne 'ARRAY' ;
183    
184     my $offset ;
185     if ($tre ne $tree) {
186     print $prefix . "|\n" ;
187     print $prefix . "+- $k" ;
188     $offset = ' ' x ($max + 4) ;
189     }
190     else {
191     print $prefix . "$k" ;
192     $offset = ' ' x ($max + 1) ;
193     }
194    
195     my ($ver, $rest) = @{ $v } ;
196     if (ref $rest)
197     {
198     my $bar = @keys ? "|" : " ";
199     print " -" . "-" x ($max - length $k ) . "+\n" ;
200     printTree ($rest, $prefix . $bar . $offset )
201     }
202     else
203     { print "\n" }
204     }
205    
206     }
207    
208     ###########################################################################
209    
210     sub mkHexOct
211     {
212     my ($f, $max, @a) = @_ ;
213     my $mask = "\x00" x $max ;
214     my $string = "" ;
215    
216     foreach (@a) {
217     vec($mask, $_, 1) = 1 ;
218     }
219    
220     foreach (unpack("C*", $mask)) {
221     if ($f eq 'x') {
222     $string .= '\x' . sprintf("%2.2x", $_)
223     }
224     else {
225     $string .= '\\' . sprintf("%o", $_)
226     }
227     }
228     return $string ;
229     }
230    
231     sub mkHex
232     {
233     my($max, @a) = @_;
234     return mkHexOct("x", $max, @a);
235     }
236    
237     sub mkOct
238     {
239     my($max, @a) = @_;
240     return mkHexOct("o", $max, @a);
241     }
242    
243     ###########################################################################
244    
245     if (@ARGV && $ARGV[0] eq "tree")
246     {
247     printTree($tree, " ") ;
248     exit ;
249     }
250    
251     unlink "warnings.h";
252     unlink "lib/warnings.pm";
253     open(WARN, ">warnings.h") || die "Can't create warnings.h: $!\n";
254     binmode WARN;
255     open(PM, ">lib/warnings.pm") || die "Can't create lib/warnings.pm: $!\n";
256     binmode PM;
257    
258     print WARN <<'EOM' ;
259     /* !!!!!!! DO NOT EDIT THIS FILE !!!!!!!
260     This file is built by warnings.pl
261     Any changes made here will be lost!
262     */
263    
264    
265     #define Off(x) ((x) / 8)
266     #define Bit(x) (1 << ((x) % 8))
267     #define IsSet(a, x) ((a)[Off(x)] & Bit(x))
268    
269    
270     #define G_WARN_OFF 0 /* $^W == 0 */
271     #define G_WARN_ON 1 /* -w flag and $^W != 0 */
272     #define G_WARN_ALL_ON 2 /* -W flag */
273     #define G_WARN_ALL_OFF 4 /* -X flag */
274     #define G_WARN_ONCE 8 /* set if 'once' ever enabled */
275     #define G_WARN_ALL_MASK (G_WARN_ALL_ON|G_WARN_ALL_OFF)
276    
277     #define pWARN_STD Nullsv
278     #define pWARN_ALL (Nullsv+1) /* use warnings 'all' */
279     #define pWARN_NONE (Nullsv+2) /* no warnings 'all' */
280    
281     #define specialWARN(x) ((x) == pWARN_STD || (x) == pWARN_ALL || \
282     (x) == pWARN_NONE)
283     EOM
284    
285     my $offset = 0 ;
286    
287     $index = $offset ;
288     #@{ $list{"all"} } = walk ($tree) ;
289     valueWalk ($tree) ;
290     my $index = orderValues();
291    
292     die <<EOM if $index > 255 ;
293     Too many warnings categories -- max is 255
294     rewrite packWARN* & unpackWARN* macros
295     EOM
296    
297     walk ($tree) ;
298    
299     $index *= 2 ;
300     my $warn_size = int($index / 8) + ($index % 8 != 0) ;
301    
302     my $k ;
303     my $last_ver = 0;
304     foreach $k (sort { $a <=> $b } keys %ValueToName) {
305     my ($name, $version) = @{ $ValueToName{$k} };
306     print WARN "\n/* Warnings Categories added in Perl $version */\n\n"
307     if $last_ver != $version ;
308     print WARN tab(5, "#define WARN_$name"), "$k\n" ;
309     $last_ver = $version ;
310     }
311     print WARN "\n" ;
312    
313     print WARN tab(5, '#define WARNsize'), "$warn_size\n" ;
314     #print WARN tab(5, '#define WARN_ALLstring'), '"', ('\377' x $warn_size) , "\"\n" ;
315     print WARN tab(5, '#define WARN_ALLstring'), '"', ('\125' x $warn_size) , "\"\n" ;
316     print WARN tab(5, '#define WARN_NONEstring'), '"', ('\0' x $warn_size) , "\"\n" ;
317     my $WARN_TAINTstring = mkOct($warn_size, map $_ * 2, @{ $list{'taint'} });
318    
319     print WARN tab(5, '#define WARN_TAINTstring'), qq["$WARN_TAINTstring"\n] ;
320    
321     print WARN <<'EOM';
322    
323     #define isLEXWARN_on (PL_curcop->cop_warnings != pWARN_STD)
324     #define isLEXWARN_off (PL_curcop->cop_warnings == pWARN_STD)
325     #define isWARN_ONCE (PL_dowarn & (G_WARN_ON|G_WARN_ONCE))
326     #define isWARN_on(c,x) (IsSet(SvPVX(c), 2*(x)))
327     #define isWARNf_on(c,x) (IsSet(SvPVX(c), 2*(x)+1))
328    
329     #define ckWARN(x) \
330     ( (isLEXWARN_on && PL_curcop->cop_warnings != pWARN_NONE && \
331     (PL_curcop->cop_warnings == pWARN_ALL || \
332     isWARN_on(PL_curcop->cop_warnings, x) ) ) \
333     || (isLEXWARN_off && PL_dowarn & G_WARN_ON) )
334    
335     #define ckWARN2(x,y) \
336     ( (isLEXWARN_on && PL_curcop->cop_warnings != pWARN_NONE && \
337     (PL_curcop->cop_warnings == pWARN_ALL || \
338     isWARN_on(PL_curcop->cop_warnings, x) || \
339     isWARN_on(PL_curcop->cop_warnings, y) ) ) \
340     || (isLEXWARN_off && PL_dowarn & G_WARN_ON) )
341    
342     #define ckWARN3(x,y,z) \
343     ( (isLEXWARN_on && PL_curcop->cop_warnings != pWARN_NONE && \
344     (PL_curcop->cop_warnings == pWARN_ALL || \
345     isWARN_on(PL_curcop->cop_warnings, x) || \
346     isWARN_on(PL_curcop->cop_warnings, y) || \
347     isWARN_on(PL_curcop->cop_warnings, z) ) ) \
348     || (isLEXWARN_off && PL_dowarn & G_WARN_ON) )
349    
350     #define ckWARN4(x,y,z,t) \
351     ( (isLEXWARN_on && PL_curcop->cop_warnings != pWARN_NONE && \
352     (PL_curcop->cop_warnings == pWARN_ALL || \
353     isWARN_on(PL_curcop->cop_warnings, x) || \
354     isWARN_on(PL_curcop->cop_warnings, y) || \
355     isWARN_on(PL_curcop->cop_warnings, z) || \
356     isWARN_on(PL_curcop->cop_warnings, t) ) ) \
357     || (isLEXWARN_off && PL_dowarn & G_WARN_ON) )
358    
359     #define ckWARN_d(x) \
360     (isLEXWARN_off || PL_curcop->cop_warnings == pWARN_ALL || \
361     (PL_curcop->cop_warnings != pWARN_NONE && \
362     isWARN_on(PL_curcop->cop_warnings, x) ) )
363    
364     #define ckWARN2_d(x,y) \
365     (isLEXWARN_off || PL_curcop->cop_warnings == pWARN_ALL || \
366     (PL_curcop->cop_warnings != pWARN_NONE && \
367     (isWARN_on(PL_curcop->cop_warnings, x) || \
368     isWARN_on(PL_curcop->cop_warnings, y) ) ) )
369    
370     #define ckWARN3_d(x,y,z) \
371     (isLEXWARN_off || PL_curcop->cop_warnings == pWARN_ALL || \
372     (PL_curcop->cop_warnings != pWARN_NONE && \
373     (isWARN_on(PL_curcop->cop_warnings, x) || \
374     isWARN_on(PL_curcop->cop_warnings, y) || \
375     isWARN_on(PL_curcop->cop_warnings, z) ) ) )
376    
377     #define ckWARN4_d(x,y,z,t) \
378     (isLEXWARN_off || PL_curcop->cop_warnings == pWARN_ALL || \
379     (PL_curcop->cop_warnings != pWARN_NONE && \
380     (isWARN_on(PL_curcop->cop_warnings, x) || \
381     isWARN_on(PL_curcop->cop_warnings, y) || \
382     isWARN_on(PL_curcop->cop_warnings, z) || \
383     isWARN_on(PL_curcop->cop_warnings, t) ) ) )
384    
385     #define packWARN(a) (a )
386     #define packWARN2(a,b) ((a) | (b)<<8 )
387     #define packWARN3(a,b,c) ((a) | (b)<<8 | (c) <<16 )
388     #define packWARN4(a,b,c,d) ((a) | (b)<<8 | (c) <<16 | (d) <<24)
389    
390     #define unpackWARN1(x) ((x) & 0xFF)
391     #define unpackWARN2(x) (((x) >>8) & 0xFF)
392     #define unpackWARN3(x) (((x) >>16) & 0xFF)
393     #define unpackWARN4(x) (((x) >>24) & 0xFF)
394    
395     #define ckDEAD(x) \
396     ( ! specialWARN(PL_curcop->cop_warnings) && \
397     ( isWARNf_on(PL_curcop->cop_warnings, WARN_ALL) || \
398     isWARNf_on(PL_curcop->cop_warnings, unpackWARN1(x)) || \
399     isWARNf_on(PL_curcop->cop_warnings, unpackWARN2(x)) || \
400     isWARNf_on(PL_curcop->cop_warnings, unpackWARN3(x)) || \
401     isWARNf_on(PL_curcop->cop_warnings, unpackWARN4(x))))
402    
403     /* end of file warnings.h */
404    
405     EOM
406    
407     close WARN ;
408    
409     while (<DATA>) {
410     last if /^KEYWORDS$/ ;
411     print PM $_ ;
412     }
413    
414     #$list{'all'} = [ $offset .. 8 * ($warn_size/2) - 1 ] ;
415    
416     $last_ver = 0;
417     print PM "our %Offsets = (\n" ;
418     foreach my $k (sort { $a <=> $b } keys %ValueToName) {
419     my ($name, $version) = @{ $ValueToName{$k} };
420     $name = lc $name;
421     $k *= 2 ;
422     if ( $last_ver != $version ) {
423     print PM "\n";
424     print PM tab(4, " # Warnings Categories added in Perl $version");
425     print PM "\n\n";
426     }
427     print PM tab(4, " '$name'"), "=> $k,\n" ;
428     $last_ver = $version;
429     }
430    
431     print PM " );\n\n" ;
432    
433     print PM "our %Bits = (\n" ;
434     foreach $k (sort keys %list) {
435    
436     my $v = $list{$k} ;
437     my @list = sort { $a <=> $b } @$v ;
438    
439     print PM tab(4, " '$k'"), '=> "',
440     # mkHex($warn_size, @list),
441     mkHex($warn_size, map $_ * 2 , @list),
442     '", # [', mkRange(@list), "]\n" ;
443     }
444    
445     print PM " );\n\n" ;
446    
447     print PM "our %DeadBits = (\n" ;
448     foreach $k (sort keys %list) {
449    
450     my $v = $list{$k} ;
451     my @list = sort { $a <=> $b } @$v ;
452    
453     print PM tab(4, " '$k'"), '=> "',
454     # mkHex($warn_size, @list),
455     mkHex($warn_size, map $_ * 2 + 1 , @list),
456     '", # [', mkRange(@list), "]\n" ;
457     }
458    
459     print PM " );\n\n" ;
460     print PM '$NONE = "', ('\0' x $warn_size) , "\";\n" ;
461     print PM '$LAST_BIT = ' . "$index ;\n" ;
462     print PM '$BYTES = ' . "$warn_size ;\n" ;
463     while (<DATA>) {
464     print PM $_ ;
465     }
466    
467     close PM ;
468    
469     __END__
470    
471     # !!!!!!! DO NOT EDIT THIS FILE !!!!!!!
472     # This file was created by warnings.pl
473     # Any changes made here will be lost.
474     #
475    
476     package warnings;
477    
478     our $VERSION = '1.03';
479    
480     =head1 NAME
481    
482     warnings - Perl pragma to control optional warnings
483    
484     =head1 SYNOPSIS
485    
486     use warnings;
487     no warnings;
488    
489     use warnings "all";
490     no warnings "all";
491    
492     use warnings::register;
493     if (warnings::enabled()) {
494     warnings::warn("some warning");
495     }
496    
497     if (warnings::enabled("void")) {
498     warnings::warn("void", "some warning");
499     }
500    
501     if (warnings::enabled($object)) {
502     warnings::warn($object, "some warning");
503     }
504    
505     warnings::warnif("some warning");
506     warnings::warnif("void", "some warning");
507     warnings::warnif($object, "some warning");
508    
509     =head1 DESCRIPTION
510    
511     The C<warnings> pragma is a replacement for the command line flag C<-w>,
512     but the pragma is limited to the enclosing block, while the flag is global.
513     See L<perllexwarn> for more information.
514    
515     If no import list is supplied, all possible warnings are either enabled
516     or disabled.
517    
518     A number of functions are provided to assist module authors.
519    
520     =over 4
521    
522     =item use warnings::register
523    
524     Creates a new warnings category with the same name as the package where
525     the call to the pragma is used.
526    
527     =item warnings::enabled()
528    
529     Use the warnings category with the same name as the current package.
530    
531     Return TRUE if that warnings category is enabled in the calling module.
532     Otherwise returns FALSE.
533    
534     =item warnings::enabled($category)
535    
536     Return TRUE if the warnings category, C<$category>, is enabled in the
537     calling module.
538     Otherwise returns FALSE.
539    
540     =item warnings::enabled($object)
541    
542     Use the name of the class for the object reference, C<$object>, as the
543     warnings category.
544    
545     Return TRUE if that warnings category is enabled in the first scope
546     where the object is used.
547     Otherwise returns FALSE.
548    
549     =item warnings::warn($message)
550    
551     Print C<$message> to STDERR.
552    
553     Use the warnings category with the same name as the current package.
554    
555     If that warnings category has been set to "FATAL" in the calling module
556     then die. Otherwise return.
557    
558     =item warnings::warn($category, $message)
559    
560     Print C<$message> to STDERR.
561    
562     If the warnings category, C<$category>, has been set to "FATAL" in the
563     calling module then die. Otherwise return.
564    
565     =item warnings::warn($object, $message)
566    
567     Print C<$message> to STDERR.
568    
569     Use the name of the class for the object reference, C<$object>, as the
570     warnings category.
571    
572     If that warnings category has been set to "FATAL" in the scope where C<$object>
573     is first used then die. Otherwise return.
574    
575    
576     =item warnings::warnif($message)
577    
578     Equivalent to:
579    
580     if (warnings::enabled())
581     { warnings::warn($message) }
582    
583     =item warnings::warnif($category, $message)
584    
585     Equivalent to:
586    
587     if (warnings::enabled($category))
588     { warnings::warn($category, $message) }
589    
590     =item warnings::warnif($object, $message)
591    
592     Equivalent to:
593    
594     if (warnings::enabled($object))
595     { warnings::warn($object, $message) }
596    
597     =back
598    
599     See L<perlmodlib/Pragmatic Modules> and L<perllexwarn>.
600    
601     =cut
602    
603     use Carp ();
604    
605     KEYWORDS
606    
607     $All = "" ; vec($All, $Offsets{'all'}, 2) = 3 ;
608    
609     sub Croaker
610     {
611     delete $Carp::CarpInternal{'warnings'};
612     Carp::croak(@_);
613     }
614    
615     sub bits
616     {
617     # called from B::Deparse.pm
618    
619     push @_, 'all' unless @_;
620    
621     my $mask;
622     my $catmask ;
623     my $fatal = 0 ;
624     my $no_fatal = 0 ;
625    
626     foreach my $word ( @_ ) {
627     if ($word eq 'FATAL') {
628     $fatal = 1;
629     $no_fatal = 0;
630     }
631     elsif ($word eq 'NONFATAL') {
632     $fatal = 0;
633     $no_fatal = 1;
634     }
635     elsif ($catmask = $Bits{$word}) {
636     $mask |= $catmask ;
637     $mask |= $DeadBits{$word} if $fatal ;
638     $mask &= ~($DeadBits{$word}|$All) if $no_fatal ;
639     }
640     else
641     { Croaker("Unknown warnings category '$word'")}
642     }
643    
644     return $mask ;
645     }
646    
647     sub import
648     {
649     shift;
650    
651     my $catmask ;
652     my $fatal = 0 ;
653     my $no_fatal = 0 ;
654    
655     my $mask = ${^WARNING_BITS} ;
656    
657     if (vec($mask, $Offsets{'all'}, 1)) {
658     $mask |= $Bits{'all'} ;
659     $mask |= $DeadBits{'all'} if vec($mask, $Offsets{'all'}+1, 1);
660     }
661    
662     push @_, 'all' unless @_;
663    
664     foreach my $word ( @_ ) {
665     if ($word eq 'FATAL') {
666     $fatal = 1;
667     $no_fatal = 0;
668     }
669     elsif ($word eq 'NONFATAL') {
670     $fatal = 0;
671     $no_fatal = 1;
672     }
673     elsif ($catmask = $Bits{$word}) {
674     $mask |= $catmask ;
675     $mask |= $DeadBits{$word} if $fatal ;
676     $mask &= ~($DeadBits{$word}|$All) if $no_fatal ;
677     }
678     else
679     { Croaker("Unknown warnings category '$word'")}
680     }
681    
682     ${^WARNING_BITS} = $mask ;
683     }
684    
685     sub unimport
686     {
687     shift;
688    
689     my $catmask ;
690     my $mask = ${^WARNING_BITS} ;
691    
692     if (vec($mask, $Offsets{'all'}, 1)) {
693     $mask |= $Bits{'all'} ;
694     $mask |= $DeadBits{'all'} if vec($mask, $Offsets{'all'}+1, 1);
695     }
696    
697     push @_, 'all' unless @_;
698    
699     foreach my $word ( @_ ) {
700     if ($word eq 'FATAL') {
701     next;
702     }
703     elsif ($catmask = $Bits{$word}) {
704     $mask &= ~($catmask | $DeadBits{$word} | $All);
705     }
706     else
707     { Croaker("Unknown warnings category '$word'")}
708     }
709    
710     ${^WARNING_BITS} = $mask ;
711     }
712    
713     my %builtin_type; @builtin_type{qw(SCALAR ARRAY HASH CODE REF GLOB LVALUE Regexp)} = ();
714    
715     sub __chk
716     {
717     my $category ;
718     my $offset ;
719     my $isobj = 0 ;
720    
721     if (@_) {
722     # check the category supplied.
723     $category = shift ;
724     if (my $type = ref $category) {
725     Croaker("not an object")
726     if exists $builtin_type{$type};
727     $category = $type;
728     $isobj = 1 ;
729     }
730     $offset = $Offsets{$category};
731     Croaker("Unknown warnings category '$category'")
732     unless defined $offset;
733     }
734     else {
735     $category = (caller(1))[0] ;
736     $offset = $Offsets{$category};
737     Croaker("package '$category' not registered for warnings")
738     unless defined $offset ;
739     }
740    
741     my $this_pkg = (caller(1))[0] ;
742     my $i = 2 ;
743     my $pkg ;
744    
745     if ($isobj) {
746     while (do { { package DB; $pkg = (caller($i++))[0] } } ) {
747     last unless @DB::args && $DB::args[0] =~ /^$category=/ ;
748     }
749     $i -= 2 ;
750     }
751     else {
752     for ($i = 2 ; $pkg = (caller($i))[0] ; ++ $i) {
753     last if $pkg ne $this_pkg ;
754     }
755     $i = 2
756     if !$pkg || $pkg eq $this_pkg ;
757     }
758    
759     my $callers_bitmask = (caller($i))[9] ;
760     return ($callers_bitmask, $offset, $i) ;
761     }
762    
763     sub enabled
764     {
765     Croaker("Usage: warnings::enabled([category])")
766     unless @_ == 1 || @_ == 0 ;
767    
768     my ($callers_bitmask, $offset, $i) = __chk(@_) ;
769    
770     return 0 unless defined $callers_bitmask ;
771     return vec($callers_bitmask, $offset, 1) ||
772     vec($callers_bitmask, $Offsets{'all'}, 1) ;
773     }
774    
775    
776     sub warn
777     {
778     Croaker("Usage: warnings::warn([category,] 'message')")
779     unless @_ == 2 || @_ == 1 ;
780    
781     my $message = pop ;
782     my ($callers_bitmask, $offset, $i) = __chk(@_) ;
783     Carp::croak($message)
784     if vec($callers_bitmask, $offset+1, 1) ||
785     vec($callers_bitmask, $Offsets{'all'}+1, 1) ;
786     Carp::carp($message) ;
787     }
788    
789     sub warnif
790     {
791     Croaker("Usage: warnings::warnif([category,] 'message')")
792     unless @_ == 2 || @_ == 1 ;
793    
794     my $message = pop ;
795     my ($callers_bitmask, $offset, $i) = __chk(@_) ;
796    
797     return
798     unless defined $callers_bitmask &&
799     (vec($callers_bitmask, $offset, 1) ||
800     vec($callers_bitmask, $Offsets{'all'}, 1)) ;
801    
802     Carp::croak($message)
803     if vec($callers_bitmask, $offset+1, 1) ||
804     vec($callers_bitmask, $Offsets{'all'}+1, 1) ;
805    
806     Carp::carp($message) ;
807     }
808    
809     1;