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