Re: [patch] refine make regen to be more selective
[p5sagit/p5-mst-13.2.git] / warnings.pl
CommitLineData
599cee73 1#!/usr/bin/perl
2
98225a64 3$VERSION = '1.02_02';
b75c8c73 4
73f0cc2d 5BEGIN {
b6b9a099 6 require 'regen_lib.pl';
7 push @INC, './lib';
73f0cc2d 8}
599cee73 9use strict ;
10
11sub DEFAULT_ON () { 1 }
12sub DEFAULT_OFF () { 2 }
13
14my $tree = {
d3a7d8c7 15
0d658bf5 16'all' => [ 5.008, {
17 'io' => [ 5.008, {
18 'pipe' => [ 5.008, DEFAULT_OFF],
19 'unopened' => [ 5.008, DEFAULT_OFF],
20 'closed' => [ 5.008, DEFAULT_OFF],
21 'newline' => [ 5.008, DEFAULT_OFF],
22 'exec' => [ 5.008, DEFAULT_OFF],
23 'layer' => [ 5.008, DEFAULT_OFF],
24 }],
25 'syntax' => [ 5.008, {
26 'ambiguous' => [ 5.008, DEFAULT_OFF],
27 'semicolon' => [ 5.008, DEFAULT_OFF],
28 'precedence' => [ 5.008, DEFAULT_OFF],
29 'bareword' => [ 5.008, DEFAULT_OFF],
30 'reserved' => [ 5.008, DEFAULT_OFF],
31 'digit' => [ 5.008, DEFAULT_OFF],
32 'parenthesis' => [ 5.008, DEFAULT_OFF],
33 'printf' => [ 5.008, DEFAULT_OFF],
34 'prototype' => [ 5.008, DEFAULT_OFF],
35 'qw' => [ 5.008, DEFAULT_OFF],
36 }],
37 'severe' => [ 5.008, {
38 'inplace' => [ 5.008, DEFAULT_ON],
39 'internal' => [ 5.008, DEFAULT_ON],
40 'debugging' => [ 5.008, DEFAULT_ON],
41 'malloc' => [ 5.008, DEFAULT_ON],
42 }],
43 'deprecated' => [ 5.008, DEFAULT_OFF],
44 'void' => [ 5.008, DEFAULT_OFF],
45 'recursion' => [ 5.008, DEFAULT_OFF],
46 'redefine' => [ 5.008, DEFAULT_OFF],
47 'numeric' => [ 5.008, DEFAULT_OFF],
48 'uninitialized' => [ 5.008, DEFAULT_OFF],
49 'once' => [ 5.008, DEFAULT_OFF],
50 'misc' => [ 5.008, DEFAULT_OFF],
51 'regexp' => [ 5.008, DEFAULT_OFF],
52 'glob' => [ 5.008, DEFAULT_OFF],
0d658bf5 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],
b88df990 65 'imprecision' => [ 5.011, DEFAULT_OFF],
8fa7688f 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
b6b9a099 253open(WARN, ">warnings.h-new") || die "Can't create warnings.h: $!\n";
254open(PM, ">lib/warnings.pm-new") || die "Can't create lib/warnings.pm: $!\n";
dfb1454f 255binmode WARN;
dfb1454f 256binmode PM;
599cee73 257
258print WARN <<'EOM' ;
37442d52 259/* -*- buffer-read-only: t -*-
260 !!!!!!! DO NOT EDIT THIS FILE !!!!!!!
4438c4b7 261 This file is built by warnings.pl
599cee73 262 Any changes made here will be lost!
263*/
264
265
0453d815 266#define Off(x) ((x) / 8)
267#define Bit(x) (1 << ((x) % 8))
599cee73 268#define IsSet(a, x) ((a)[Off(x)] & Bit(x))
269
0453d815 270
599cee73 271#define G_WARN_OFF 0 /* $^W == 0 */
0453d815 272#define G_WARN_ON 1 /* -w flag and $^W != 0 */
599cee73 273#define G_WARN_ALL_ON 2 /* -W flag */
274#define G_WARN_ALL_OFF 4 /* -X flag */
0453d815 275#define G_WARN_ONCE 8 /* set if 'once' ever enabled */
599cee73 276#define G_WARN_ALL_MASK (G_WARN_ALL_ON|G_WARN_ALL_OFF)
277
a0714e2c 278#define pWARN_STD NULL
72dc9ed5 279#define pWARN_ALL (((STRLEN*)0)+1) /* use warnings 'all' */
280#define pWARN_NONE (((STRLEN*)0)+2) /* no warnings 'all' */
599cee73 281
d3a7d8c7 282#define specialWARN(x) ((x) == pWARN_STD || (x) == pWARN_ALL || \
283 (x) == pWARN_NONE)
5f2d9966 284
285/* if PL_warnhook is set to this value, then warnings die */
06dcd5bf 286#define PERL_WARNHOOK_FATAL (&PL_sv_placeholder)
599cee73 287EOM
288
d3a7d8c7 289my $offset = 0 ;
290
291$index = $offset ;
292#@{ $list{"all"} } = walk ($tree) ;
0d658bf5 293valueWalk ($tree) ;
294my $index = orderValues();
599cee73 295
12bcd1a6 296die <<EOM if $index > 255 ;
297Too many warnings categories -- max is 255
298 rewrite packWARN* & unpackWARN* macros
299EOM
599cee73 300
0d658bf5 301walk ($tree) ;
302
599cee73 303$index *= 2 ;
304my $warn_size = int($index / 8) + ($index % 8 != 0) ;
305
306my $k ;
0d658bf5 307my $last_ver = 0;
308foreach $k (sort { $a <=> $b } keys %ValueToName) {
309 my ($name, $version) = @{ $ValueToName{$k} };
310 print WARN "\n/* Warnings Categories added in Perl $version */\n\n"
311 if $last_ver != $version ;
312 print WARN tab(5, "#define WARN_$name"), "$k\n" ;
313 $last_ver = $version ;
599cee73 314}
315print WARN "\n" ;
316
317print WARN tab(5, '#define WARNsize'), "$warn_size\n" ;
318#print WARN tab(5, '#define WARN_ALLstring'), '"', ('\377' x $warn_size) , "\"\n" ;
319print WARN tab(5, '#define WARN_ALLstring'), '"', ('\125' x $warn_size) , "\"\n" ;
320print WARN tab(5, '#define WARN_NONEstring'), '"', ('\0' x $warn_size) , "\"\n" ;
321
322print WARN <<'EOM';
323
d5a71f30 324#define isLEXWARN_on (PL_curcop->cop_warnings != pWARN_STD)
325#define isLEXWARN_off (PL_curcop->cop_warnings == pWARN_STD)
326#define isWARN_ONCE (PL_dowarn & (G_WARN_ON|G_WARN_ONCE))
72dc9ed5 327#define isWARN_on(c,x) (IsSet((U8 *)(c + 1), 2*(x)))
328#define isWARNf_on(c,x) (IsSet((U8 *)(c + 1), 2*(x)+1))
329
330#define DUP_WARNINGS(p) \
594cd643 331 (specialWARN(p) ? (STRLEN*)(p) \
332 : (STRLEN*)CopyD(p, PerlMemShared_malloc(sizeof(*p)+*p), sizeof(*p)+*p, \
333 char))
d5a71f30 334
f54ba1c2 335#define ckWARN(w) Perl_ckwarn(aTHX_ packWARN(w))
336#define ckWARN2(w1,w2) Perl_ckwarn(aTHX_ packWARN2(w1,w2))
337#define ckWARN3(w1,w2,w3) Perl_ckwarn(aTHX_ packWARN3(w1,w2,w3))
338#define ckWARN4(w1,w2,w3,w4) Perl_ckwarn(aTHX_ packWARN4(w1,w2,w3,w4))
339
340#define ckWARN_d(w) Perl_ckwarn_d(aTHX_ packWARN(w))
341#define ckWARN2_d(w1,w2) Perl_ckwarn_d(aTHX_ packWARN2(w1,w2))
342#define ckWARN3_d(w1,w2,w3) Perl_ckwarn_d(aTHX_ packWARN3(w1,w2,w3))
343#define ckWARN4_d(w1,w2,w3,w4) Perl_ckwarn_d(aTHX_ packWARN4(w1,w2,w3,w4))
12bcd1a6 344
3b9e3074 345#define packWARN(a) (a )
346#define packWARN2(a,b) ((a) | ((b)<<8) )
347#define packWARN3(a,b,c) ((a) | ((b)<<8) | ((c)<<16) )
348#define packWARN4(a,b,c,d) ((a) | ((b)<<8) | ((c)<<16) | ((d) <<24))
12bcd1a6 349
350#define unpackWARN1(x) ((x) & 0xFF)
351#define unpackWARN2(x) (((x) >>8) & 0xFF)
352#define unpackWARN3(x) (((x) >>16) & 0xFF)
353#define unpackWARN4(x) (((x) >>24) & 0xFF)
354
355#define ckDEAD(x) \
356 ( ! specialWARN(PL_curcop->cop_warnings) && \
357 ( isWARNf_on(PL_curcop->cop_warnings, WARN_ALL) || \
358 isWARNf_on(PL_curcop->cop_warnings, unpackWARN1(x)) || \
359 isWARNf_on(PL_curcop->cop_warnings, unpackWARN2(x)) || \
360 isWARNf_on(PL_curcop->cop_warnings, unpackWARN3(x)) || \
361 isWARNf_on(PL_curcop->cop_warnings, unpackWARN4(x))))
362
4438c4b7 363/* end of file warnings.h */
37442d52 364/* ex: set ro: */
599cee73 365EOM
366
367close WARN ;
b6b9a099 368safer_rename("warnings.h-new", "warnings.h");
599cee73 369
370while (<DATA>) {
371 last if /^KEYWORDS$/ ;
372 print PM $_ ;
373}
374
d3a7d8c7 375#$list{'all'} = [ $offset .. 8 * ($warn_size/2) - 1 ] ;
376
0d658bf5 377$last_ver = 0;
53c33732 378print PM "our %Offsets = (\n" ;
0d658bf5 379foreach my $k (sort { $a <=> $b } keys %ValueToName) {
380 my ($name, $version) = @{ $ValueToName{$k} };
381 $name = lc $name;
d3a7d8c7 382 $k *= 2 ;
0d658bf5 383 if ( $last_ver != $version ) {
384 print PM "\n";
385 print PM tab(4, " # Warnings Categories added in Perl $version");
386 print PM "\n\n";
387 }
388 print PM tab(4, " '$name'"), "=> $k,\n" ;
389 $last_ver = $version;
d3a7d8c7 390}
391
392print PM " );\n\n" ;
393
53c33732 394print PM "our %Bits = (\n" ;
599cee73 395foreach $k (sort keys %list) {
396
397 my $v = $list{$k} ;
398 my @list = sort { $a <=> $b } @$v ;
399
0ca4541c 400 print PM tab(4, " '$k'"), '=> "',
401 # mkHex($warn_size, @list),
402 mkHex($warn_size, map $_ * 2 , @list),
599cee73 403 '", # [', mkRange(@list), "]\n" ;
404}
405
406print PM " );\n\n" ;
407
53c33732 408print PM "our %DeadBits = (\n" ;
599cee73 409foreach $k (sort keys %list) {
410
411 my $v = $list{$k} ;
412 my @list = sort { $a <=> $b } @$v ;
413
0ca4541c 414 print PM tab(4, " '$k'"), '=> "',
415 # mkHex($warn_size, @list),
416 mkHex($warn_size, map $_ * 2 + 1 , @list),
599cee73 417 '", # [', mkRange(@list), "]\n" ;
418}
419
420print PM " );\n\n" ;
d3a7d8c7 421print PM '$NONE = "', ('\0' x $warn_size) , "\";\n" ;
422print PM '$LAST_BIT = ' . "$index ;\n" ;
423print PM '$BYTES = ' . "$warn_size ;\n" ;
599cee73 424while (<DATA>) {
425 print PM $_ ;
426}
427
37442d52 428print PM "# ex: set ro:\n";
599cee73 429close PM ;
b6b9a099 430safer_rename("lib/warnings.pm-new", "lib/warnings.pm");
599cee73 431
432__END__
37442d52 433# -*- buffer-read-only: t -*-
38875929 434# !!!!!!! DO NOT EDIT THIS FILE !!!!!!!
4438c4b7 435# This file was created by warnings.pl
599cee73 436# Any changes made here will be lost.
437#
438
4438c4b7 439package warnings;
599cee73 440
f2c3e829 441our $VERSION = '1.06';
442
443# Verify that we're called correctly so that warnings will work.
444# see also strict.pm.
5108dc18 445unless ( __FILE__ =~ /(^|[\/\\])\Q${\__PACKAGE__}\E\.pmc?$/ ) {
f2c3e829 446 my (undef, $f, $l) = caller;
5108dc18 447 die("Incorrect use of pragma '${\__PACKAGE__}' at $f line $l.\n");
f2c3e829 448}
b75c8c73 449
599cee73 450=head1 NAME
451
4438c4b7 452warnings - Perl pragma to control optional warnings
599cee73 453
454=head1 SYNOPSIS
455
4438c4b7 456 use warnings;
457 no warnings;
599cee73 458
4438c4b7 459 use warnings "all";
460 no warnings "all";
599cee73 461
d3a7d8c7 462 use warnings::register;
463 if (warnings::enabled()) {
464 warnings::warn("some warning");
465 }
466
467 if (warnings::enabled("void")) {
e476b1b5 468 warnings::warn("void", "some warning");
469 }
470
7e6d00f8 471 if (warnings::enabled($object)) {
472 warnings::warn($object, "some warning");
473 }
474
721f911b 475 warnings::warnif("some warning");
476 warnings::warnif("void", "some warning");
477 warnings::warnif($object, "some warning");
7e6d00f8 478
599cee73 479=head1 DESCRIPTION
480
fe2e802c 481The C<warnings> pragma is a replacement for the command line flag C<-w>,
482but the pragma is limited to the enclosing block, while the flag is global.
483See L<perllexwarn> for more information.
484
0453d815 485If no import list is supplied, all possible warnings are either enabled
486or disabled.
599cee73 487
0ca4541c 488A number of functions are provided to assist module authors.
e476b1b5 489
490=over 4
491
d3a7d8c7 492=item use warnings::register
493
7e6d00f8 494Creates a new warnings category with the same name as the package where
495the call to the pragma is used.
496
497=item warnings::enabled()
498
499Use the warnings category with the same name as the current package.
500
501Return TRUE if that warnings category is enabled in the calling module.
502Otherwise returns FALSE.
503
504=item warnings::enabled($category)
505
506Return TRUE if the warnings category, C<$category>, is enabled in the
507calling module.
508Otherwise returns FALSE.
509
510=item warnings::enabled($object)
511
512Use the name of the class for the object reference, C<$object>, as the
513warnings category.
514
515Return TRUE if that warnings category is enabled in the first scope
516where the object is used.
517Otherwise returns FALSE.
518
519=item warnings::warn($message)
520
521Print C<$message> to STDERR.
522
523Use the warnings category with the same name as the current package.
524
525If that warnings category has been set to "FATAL" in the calling module
526then die. Otherwise return.
527
528=item warnings::warn($category, $message)
529
530Print C<$message> to STDERR.
531
532If the warnings category, C<$category>, has been set to "FATAL" in the
533calling module then die. Otherwise return.
d3a7d8c7 534
7e6d00f8 535=item warnings::warn($object, $message)
e476b1b5 536
7e6d00f8 537Print C<$message> to STDERR.
e476b1b5 538
7e6d00f8 539Use the name of the class for the object reference, C<$object>, as the
540warnings category.
e476b1b5 541
7e6d00f8 542If that warnings category has been set to "FATAL" in the scope where C<$object>
543is first used then die. Otherwise return.
599cee73 544
e476b1b5 545
7e6d00f8 546=item warnings::warnif($message)
547
548Equivalent to:
549
550 if (warnings::enabled())
551 { warnings::warn($message) }
552
553=item warnings::warnif($category, $message)
554
555Equivalent to:
556
557 if (warnings::enabled($category))
558 { warnings::warn($category, $message) }
559
560=item warnings::warnif($object, $message)
561
562Equivalent to:
563
564 if (warnings::enabled($object))
565 { warnings::warn($object, $message) }
d3a7d8c7 566
e476b1b5 567=back
568
749f83fa 569See L<perlmodlib/Pragmatic Modules> and L<perllexwarn>.
599cee73 570
571=cut
572
599cee73 573KEYWORDS
574
d3a7d8c7 575$All = "" ; vec($All, $Offsets{'all'}, 2) = 3 ;
576
c3186b65 577sub Croaker
578{
29ddba3b 579 require Carp::Heavy; # this initializes %CarpInternal
dbab294c 580 local $Carp::CarpInternal{'warnings'};
c3186b65 581 delete $Carp::CarpInternal{'warnings'};
8becbb3b 582 Carp::croak(@_);
c3186b65 583}
584
6e9af7e4 585sub bits
586{
587 # called from B::Deparse.pm
588
589 push @_, 'all' unless @_;
590
591 my $mask;
599cee73 592 my $catmask ;
593 my $fatal = 0 ;
6e9af7e4 594 my $no_fatal = 0 ;
595
596 foreach my $word ( @_ ) {
597 if ($word eq 'FATAL') {
327afb7f 598 $fatal = 1;
6e9af7e4 599 $no_fatal = 0;
600 }
601 elsif ($word eq 'NONFATAL') {
602 $fatal = 0;
603 $no_fatal = 1;
327afb7f 604 }
d3a7d8c7 605 elsif ($catmask = $Bits{$word}) {
606 $mask |= $catmask ;
607 $mask |= $DeadBits{$word} if $fatal ;
6e9af7e4 608 $mask &= ~($DeadBits{$word}|$All) if $no_fatal ;
599cee73 609 }
d3a7d8c7 610 else
c3186b65 611 { Croaker("Unknown warnings category '$word'")}
599cee73 612 }
613
614 return $mask ;
615}
616
6e9af7e4 617sub import
618{
599cee73 619 shift;
6e9af7e4 620
621 my $catmask ;
622 my $fatal = 0 ;
623 my $no_fatal = 0 ;
624
f1f33818 625 my $mask = ${^WARNING_BITS} ;
6e9af7e4 626
f1f33818 627 if (vec($mask, $Offsets{'all'}, 1)) {
628 $mask |= $Bits{'all'} ;
629 $mask |= $DeadBits{'all'} if vec($mask, $Offsets{'all'}+1, 1);
630 }
6e9af7e4 631
632 push @_, 'all' unless @_;
633
634 foreach my $word ( @_ ) {
635 if ($word eq 'FATAL') {
636 $fatal = 1;
637 $no_fatal = 0;
638 }
639 elsif ($word eq 'NONFATAL') {
640 $fatal = 0;
641 $no_fatal = 1;
642 }
643 elsif ($catmask = $Bits{$word}) {
644 $mask |= $catmask ;
645 $mask |= $DeadBits{$word} if $fatal ;
646 $mask &= ~($DeadBits{$word}|$All) if $no_fatal ;
647 }
648 else
649 { Croaker("Unknown warnings category '$word'")}
650 }
651
652 ${^WARNING_BITS} = $mask ;
599cee73 653}
654
6e9af7e4 655sub unimport
656{
599cee73 657 shift;
6e9af7e4 658
659 my $catmask ;
d3a7d8c7 660 my $mask = ${^WARNING_BITS} ;
6e9af7e4 661
d3a7d8c7 662 if (vec($mask, $Offsets{'all'}, 1)) {
f1f33818 663 $mask |= $Bits{'all'} ;
d3a7d8c7 664 $mask |= $DeadBits{'all'} if vec($mask, $Offsets{'all'}+1, 1);
665 }
6e9af7e4 666
667 push @_, 'all' unless @_;
668
669 foreach my $word ( @_ ) {
670 if ($word eq 'FATAL') {
671 next;
672 }
673 elsif ($catmask = $Bits{$word}) {
674 $mask &= ~($catmask | $DeadBits{$word} | $All);
675 }
676 else
677 { Croaker("Unknown warnings category '$word'")}
678 }
679
680 ${^WARNING_BITS} = $mask ;
599cee73 681}
682
9df0f64f 683my %builtin_type; @builtin_type{qw(SCALAR ARRAY HASH CODE REF GLOB LVALUE Regexp)} = ();
684
7e6d00f8 685sub __chk
599cee73 686{
d3a7d8c7 687 my $category ;
688 my $offset ;
7e6d00f8 689 my $isobj = 0 ;
d3a7d8c7 690
691 if (@_) {
692 # check the category supplied.
693 $category = shift ;
9df0f64f 694 if (my $type = ref $category) {
695 Croaker("not an object")
696 if exists $builtin_type{$type};
697 $category = $type;
7e6d00f8 698 $isobj = 1 ;
699 }
d3a7d8c7 700 $offset = $Offsets{$category};
c3186b65 701 Croaker("Unknown warnings category '$category'")
d3a7d8c7 702 unless defined $offset;
703 }
704 else {
0ca4541c 705 $category = (caller(1))[0] ;
d3a7d8c7 706 $offset = $Offsets{$category};
c3186b65 707 Croaker("package '$category' not registered for warnings")
d3a7d8c7 708 unless defined $offset ;
709 }
710
0ca4541c 711 my $this_pkg = (caller(1))[0] ;
7e6d00f8 712 my $i = 2 ;
713 my $pkg ;
714
715 if ($isobj) {
716 while (do { { package DB; $pkg = (caller($i++))[0] } } ) {
717 last unless @DB::args && $DB::args[0] =~ /^$category=/ ;
718 }
719 $i -= 2 ;
720 }
721 else {
4f527b71 722 $i = _error_loc(); # see where Carp will allocate the error
7e6d00f8 723 }
724
0ca4541c 725 my $callers_bitmask = (caller($i))[9] ;
7e6d00f8 726 return ($callers_bitmask, $offset, $i) ;
727}
728
4f527b71 729sub _error_loc {
730 require Carp::Heavy;
731 goto &Carp::short_error_loc; # don't introduce another stack frame
732}
733
7e6d00f8 734sub enabled
735{
c3186b65 736 Croaker("Usage: warnings::enabled([category])")
7e6d00f8 737 unless @_ == 1 || @_ == 0 ;
738
739 my ($callers_bitmask, $offset, $i) = __chk(@_) ;
740
741 return 0 unless defined $callers_bitmask ;
d3a7d8c7 742 return vec($callers_bitmask, $offset, 1) ||
743 vec($callers_bitmask, $Offsets{'all'}, 1) ;
599cee73 744}
745
d3a7d8c7 746
e476b1b5 747sub warn
748{
c3186b65 749 Croaker("Usage: warnings::warn([category,] 'message')")
d3a7d8c7 750 unless @_ == 2 || @_ == 1 ;
d3a7d8c7 751
7e6d00f8 752 my $message = pop ;
753 my ($callers_bitmask, $offset, $i) = __chk(@_) ;
09e96b99 754 require Carp;
8becbb3b 755 Carp::croak($message)
d3a7d8c7 756 if vec($callers_bitmask, $offset+1, 1) ||
757 vec($callers_bitmask, $Offsets{'all'}+1, 1) ;
8becbb3b 758 Carp::carp($message) ;
e476b1b5 759}
760
7e6d00f8 761sub warnif
762{
c3186b65 763 Croaker("Usage: warnings::warnif([category,] 'message')")
7e6d00f8 764 unless @_ == 2 || @_ == 1 ;
765
766 my $message = pop ;
767 my ($callers_bitmask, $offset, $i) = __chk(@_) ;
7e6d00f8 768
0ca4541c 769 return
7e6d00f8 770 unless defined $callers_bitmask &&
771 (vec($callers_bitmask, $offset, 1) ||
772 vec($callers_bitmask, $Offsets{'all'}, 1)) ;
773
09e96b99 774 require Carp;
8becbb3b 775 Carp::croak($message)
7e6d00f8 776 if vec($callers_bitmask, $offset+1, 1) ||
777 vec($callers_bitmask, $Offsets{'all'}+1, 1) ;
778
8becbb3b 779 Carp::carp($message) ;
7e6d00f8 780}
0d658bf5 781
599cee73 7821;