This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Assume NetBSD has touch
[perl5.git] / warnings.pl
CommitLineData
599cee73
PM
1#!/usr/bin/perl
2
98225a64 3$VERSION = '1.02_02';
b75c8c73 4
73f0cc2d
GS
5BEGIN {
6 push @INC, './lib';
7}
599cee73
PM
8use strict ;
9
10sub DEFAULT_ON () { 1 }
11sub DEFAULT_OFF () { 2 }
12
13my $tree = {
d3a7d8c7 14
0d658bf5
PM
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],
0d658bf5
PM
52 'untie' => [ 5.008, DEFAULT_OFF],
53 'substr' => [ 5.008, DEFAULT_OFF],
54 'taint' => [ 5.008, DEFAULT_OFF],
55 'signal' => [ 5.008, DEFAULT_OFF],
56 'closure' => [ 5.008, DEFAULT_OFF],
57 'overflow' => [ 5.008, DEFAULT_OFF],
58 'portable' => [ 5.008, DEFAULT_OFF],
59 'utf8' => [ 5.008, DEFAULT_OFF],
60 'exiting' => [ 5.008, DEFAULT_OFF],
61 'pack' => [ 5.008, DEFAULT_OFF],
62 'unpack' => [ 5.008, DEFAULT_OFF],
38875929 63 'threads' => [ 5.008, DEFAULT_OFF],
8fa7688f 64
0d658bf5
PM
65 #'default' => [ 5.008, DEFAULT_ON ],
66 }],
d3a7d8c7 67} ;
599cee73 68
599cee73
PM
69###########################################################################
70sub tab {
71 my($l, $t) = @_;
72 $t .= "\t" x ($l - (length($t) + 1) / 8);
73 $t;
74}
75
76###########################################################################
77
78my %list ;
79my %Value ;
0d658bf5
PM
80my %ValueToName ;
81my %NameToValue ;
d3a7d8c7 82my $index ;
599cee73 83
0d658bf5
PM
84my %v_list = () ;
85
86sub 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
108sub 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
599cee73
PM
123sub walk
124{
125 my $tre = shift ;
126 my @list = () ;
127 my ($k, $v) ;
128
95dfd3ab
GS
129 foreach $k (sort keys %$tre) {
130 $v = $tre->{$k};
599cee73 131 die "duplicate key $k\n" if defined $list{$k} ;
0d658bf5
PM
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
599cee73
PM
143 push @list, @{ $list{$k} } ;
144 }
145
146 return @list ;
599cee73
PM
147}
148
149###########################################################################
150
151sub mkRange
152{
153 my @a = @_ ;
154 my @out = @a ;
155 my $i ;
156
157
158 for ($i = 1 ; $i < @a; ++ $i) {
0ca4541c 159 $out[$i] = ".."
599cee73
PM
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###########################################################################
e476b1b5
GS
170sub printTree
171{
172 my $tre = shift ;
173 my $prefix = shift ;
e476b1b5
GS
174 my ($k, $v) ;
175
176 my $max = (sort {$a <=> $b} map { length $_ } keys %$tre)[-1] ;
0d658bf5 177 my @keys = sort keys %$tre ;
e476b1b5 178
0d658bf5 179 while ($k = shift @keys) {
e476b1b5 180 $v = $tre->{$k};
0d658bf5
PM
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)
0ca4541c 197 {
0d658bf5
PM
198 my $bar = @keys ? "|" : " ";
199 print " -" . "-" x ($max - length $k ) . "+\n" ;
200 printTree ($rest, $prefix . $bar . $offset )
e476b1b5
GS
201 }
202 else
203 { print "\n" }
204 }
205
206}
207
208###########################################################################
599cee73 209
317ea90d 210sub mkHexOct
599cee73 211{
317ea90d 212 my ($f, $max, @a) = @_ ;
599cee73
PM
213 my $mask = "\x00" x $max ;
214 my $string = "" ;
215
216 foreach (@a) {
217 vec($mask, $_, 1) = 1 ;
218 }
219
599cee73 220 foreach (unpack("C*", $mask)) {
317ea90d
MS
221 if ($f eq 'x') {
222 $string .= '\x' . sprintf("%2.2x", $_)
223 }
224 else {
225 $string .= '\\' . sprintf("%o", $_)
226 }
599cee73
PM
227 }
228 return $string ;
229}
230
317ea90d
MS
231sub mkHex
232{
233 my($max, @a) = @_;
234 return mkHexOct("x", $max, @a);
235}
236
237sub mkOct
238{
239 my($max, @a) = @_;
240 return mkHexOct("o", $max, @a);
241}
242
599cee73
PM
243###########################################################################
244
e476b1b5
GS
245if (@ARGV && $ARGV[0] eq "tree")
246{
0d658bf5 247 printTree($tree, " ") ;
e476b1b5
GS
248 exit ;
249}
599cee73 250
918426be
NC
251unlink "warnings.h";
252unlink "lib/warnings.pm";
4438c4b7 253open(WARN, ">warnings.h") || die "Can't create warnings.h: $!\n";
dfb1454f 254binmode WARN;
4438c4b7 255open(PM, ">lib/warnings.pm") || die "Can't create lib/warnings.pm: $!\n";
dfb1454f 256binmode PM;
599cee73
PM
257
258print WARN <<'EOM' ;
37442d52
RGS
259/* -*- buffer-read-only: t -*-
260 !!!!!!! DO NOT EDIT THIS FILE !!!!!!!
4438c4b7 261 This file is built by warnings.pl
599cee73
PM
262 Any changes made here will be lost!
263*/
264
265
0453d815
PM
266#define Off(x) ((x) / 8)
267#define Bit(x) (1 << ((x) % 8))
599cee73
PM
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
PM
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
PM
276#define G_WARN_ALL_MASK (G_WARN_ALL_ON|G_WARN_ALL_OFF)
277
a0714e2c 278#define pWARN_STD NULL
72dc9ed5
NC
279#define pWARN_ALL (((STRLEN*)0)+1) /* use warnings 'all' */
280#define pWARN_NONE (((STRLEN*)0)+2) /* no warnings 'all' */
599cee73 281
d3a7d8c7
GS
282#define specialWARN(x) ((x) == pWARN_STD || (x) == pWARN_ALL || \
283 (x) == pWARN_NONE)
5f2d9966
DM
284
285/* if PL_warnhook is set to this value, then warnings die */
06dcd5bf 286#define PERL_WARNHOOK_FATAL (&PL_sv_placeholder)
599cee73
PM
287EOM
288
d3a7d8c7
GS
289my $offset = 0 ;
290
291$index = $offset ;
292#@{ $list{"all"} } = walk ($tree) ;
0d658bf5
PM
293valueWalk ($tree) ;
294my $index = orderValues();
599cee73 295
12bcd1a6
PM
296die <<EOM if $index > 255 ;
297Too many warnings categories -- max is 255
298 rewrite packWARN* & unpackWARN* macros
299EOM
599cee73 300
0d658bf5
PM
301walk ($tree) ;
302
599cee73
PM
303$index *= 2 ;
304my $warn_size = int($index / 8) + ($index % 8 != 0) ;
305
306my $k ;
0d658bf5
PM
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
PM
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
GS
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
NC
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
NC
331 (specialWARN(p) ? (STRLEN*)(p) \
332 : (STRLEN*)CopyD(p, PerlMemShared_malloc(sizeof(*p)+*p), sizeof(*p)+*p, \
333 char))
d5a71f30 334
f54ba1c2
DM
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
SH
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
PM
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
PM
365EOM
366
367close WARN ;
368
369while (<DATA>) {
370 last if /^KEYWORDS$/ ;
371 print PM $_ ;
372}
373
d3a7d8c7
GS
374#$list{'all'} = [ $offset .. 8 * ($warn_size/2) - 1 ] ;
375
0d658bf5 376$last_ver = 0;
53c33732 377print PM "our %Offsets = (\n" ;
0d658bf5
PM
378foreach my $k (sort { $a <=> $b } keys %ValueToName) {
379 my ($name, $version) = @{ $ValueToName{$k} };
380 $name = lc $name;
d3a7d8c7 381 $k *= 2 ;
0d658bf5
PM
382 if ( $last_ver != $version ) {
383 print PM "\n";
384 print PM tab(4, " # Warnings Categories added in Perl $version");
385 print PM "\n\n";
386 }
387 print PM tab(4, " '$name'"), "=> $k,\n" ;
388 $last_ver = $version;
d3a7d8c7
GS
389}
390
391print PM " );\n\n" ;
392
53c33732 393print PM "our %Bits = (\n" ;
599cee73
PM
394foreach $k (sort keys %list) {
395
396 my $v = $list{$k} ;
397 my @list = sort { $a <=> $b } @$v ;
398
0ca4541c
NIS
399 print PM tab(4, " '$k'"), '=> "',
400 # mkHex($warn_size, @list),
401 mkHex($warn_size, map $_ * 2 , @list),
599cee73
PM
402 '", # [', mkRange(@list), "]\n" ;
403}
404
405print PM " );\n\n" ;
406
53c33732 407print PM "our %DeadBits = (\n" ;
599cee73
PM
408foreach $k (sort keys %list) {
409
410 my $v = $list{$k} ;
411 my @list = sort { $a <=> $b } @$v ;
412
0ca4541c
NIS
413 print PM tab(4, " '$k'"), '=> "',
414 # mkHex($warn_size, @list),
415 mkHex($warn_size, map $_ * 2 + 1 , @list),
599cee73
PM
416 '", # [', mkRange(@list), "]\n" ;
417}
418
419print PM " );\n\n" ;
d3a7d8c7
GS
420print PM '$NONE = "', ('\0' x $warn_size) , "\";\n" ;
421print PM '$LAST_BIT = ' . "$index ;\n" ;
422print PM '$BYTES = ' . "$warn_size ;\n" ;
599cee73
PM
423while (<DATA>) {
424 print PM $_ ;
425}
426
37442d52 427print PM "# ex: set ro:\n";
599cee73
PM
428close PM ;
429
430__END__
37442d52 431# -*- buffer-read-only: t -*-
38875929 432# !!!!!!! DO NOT EDIT THIS FILE !!!!!!!
4438c4b7 433# This file was created by warnings.pl
599cee73
PM
434# Any changes made here will be lost.
435#
436
4438c4b7 437package warnings;
599cee73 438
f2c3e829
RGS
439our $VERSION = '1.06';
440
441# Verify that we're called correctly so that warnings will work.
442# see also strict.pm.
443unless ( __FILE__ =~ /(^|[\/\\])\Q@{[__PACKAGE__]}\E\.pm$/ ) {
444 my (undef, $f, $l) = caller;
445 die("Incorrect use of pragma '@{[__PACKAGE__,]}' at $f line $l.\n");
446}
b75c8c73 447
599cee73
PM
448=head1 NAME
449
4438c4b7 450warnings - Perl pragma to control optional warnings
599cee73
PM
451
452=head1 SYNOPSIS
453
4438c4b7
JH
454 use warnings;
455 no warnings;
599cee73 456
4438c4b7
JH
457 use warnings "all";
458 no warnings "all";
599cee73 459
d3a7d8c7
GS
460 use warnings::register;
461 if (warnings::enabled()) {
462 warnings::warn("some warning");
463 }
464
465 if (warnings::enabled("void")) {
e476b1b5
GS
466 warnings::warn("void", "some warning");
467 }
468
7e6d00f8
PM
469 if (warnings::enabled($object)) {
470 warnings::warn($object, "some warning");
471 }
472
721f911b
PM
473 warnings::warnif("some warning");
474 warnings::warnif("void", "some warning");
475 warnings::warnif($object, "some warning");
7e6d00f8 476
599cee73
PM
477=head1 DESCRIPTION
478
fe2e802c
EM
479The C<warnings> pragma is a replacement for the command line flag C<-w>,
480but the pragma is limited to the enclosing block, while the flag is global.
481See L<perllexwarn> for more information.
482
0453d815
PM
483If no import list is supplied, all possible warnings are either enabled
484or disabled.
599cee73 485
0ca4541c 486A number of functions are provided to assist module authors.
e476b1b5
GS
487
488=over 4
489
d3a7d8c7
GS
490=item use warnings::register
491
7e6d00f8
PM
492Creates a new warnings category with the same name as the package where
493the call to the pragma is used.
494
495=item warnings::enabled()
496
497Use the warnings category with the same name as the current package.
498
499Return TRUE if that warnings category is enabled in the calling module.
500Otherwise returns FALSE.
501
502=item warnings::enabled($category)
503
504Return TRUE if the warnings category, C<$category>, is enabled in the
505calling module.
506Otherwise returns FALSE.
507
508=item warnings::enabled($object)
509
510Use the name of the class for the object reference, C<$object>, as the
511warnings category.
512
513Return TRUE if that warnings category is enabled in the first scope
514where the object is used.
515Otherwise returns FALSE.
516
517=item warnings::warn($message)
518
519Print C<$message> to STDERR.
520
521Use the warnings category with the same name as the current package.
522
523If that warnings category has been set to "FATAL" in the calling module
524then die. Otherwise return.
525
526=item warnings::warn($category, $message)
527
528Print C<$message> to STDERR.
529
530If the warnings category, C<$category>, has been set to "FATAL" in the
531calling module then die. Otherwise return.
d3a7d8c7 532
7e6d00f8 533=item warnings::warn($object, $message)
e476b1b5 534
7e6d00f8 535Print C<$message> to STDERR.
e476b1b5 536
7e6d00f8
PM
537Use the name of the class for the object reference, C<$object>, as the
538warnings category.
e476b1b5 539
7e6d00f8
PM
540If that warnings category has been set to "FATAL" in the scope where C<$object>
541is first used then die. Otherwise return.
599cee73 542
e476b1b5 543
7e6d00f8
PM
544=item warnings::warnif($message)
545
546Equivalent to:
547
548 if (warnings::enabled())
549 { warnings::warn($message) }
550
551=item warnings::warnif($category, $message)
552
553Equivalent to:
554
555 if (warnings::enabled($category))
556 { warnings::warn($category, $message) }
557
558=item warnings::warnif($object, $message)
559
560Equivalent to:
561
562 if (warnings::enabled($object))
563 { warnings::warn($object, $message) }
d3a7d8c7 564
e476b1b5
GS
565=back
566
749f83fa 567See L<perlmodlib/Pragmatic Modules> and L<perllexwarn>.
599cee73
PM
568
569=cut
570
599cee73
PM
571KEYWORDS
572
d3a7d8c7
GS
573$All = "" ; vec($All, $Offsets{'all'}, 2) = 3 ;
574
c3186b65
PM
575sub Croaker
576{
29ddba3b 577 require Carp::Heavy; # this initializes %CarpInternal
dbab294c 578 local $Carp::CarpInternal{'warnings'};
c3186b65 579 delete $Carp::CarpInternal{'warnings'};
8becbb3b 580 Carp::croak(@_);
c3186b65
PM
581}
582
6e9af7e4
PM
583sub bits
584{
585 # called from B::Deparse.pm
586
587 push @_, 'all' unless @_;
588
589 my $mask;
599cee73
PM
590 my $catmask ;
591 my $fatal = 0 ;
6e9af7e4
PM
592 my $no_fatal = 0 ;
593
594 foreach my $word ( @_ ) {
595 if ($word eq 'FATAL') {
327afb7f 596 $fatal = 1;
6e9af7e4
PM
597 $no_fatal = 0;
598 }
599 elsif ($word eq 'NONFATAL') {
600 $fatal = 0;
601 $no_fatal = 1;
327afb7f 602 }
d3a7d8c7
GS
603 elsif ($catmask = $Bits{$word}) {
604 $mask |= $catmask ;
605 $mask |= $DeadBits{$word} if $fatal ;
6e9af7e4 606 $mask &= ~($DeadBits{$word}|$All) if $no_fatal ;
599cee73 607 }
d3a7d8c7 608 else
c3186b65 609 { Croaker("Unknown warnings category '$word'")}
599cee73
PM
610 }
611
612 return $mask ;
613}
614
6e9af7e4
PM
615sub import
616{
599cee73 617 shift;
6e9af7e4
PM
618
619 my $catmask ;
620 my $fatal = 0 ;
621 my $no_fatal = 0 ;
622
f1f33818 623 my $mask = ${^WARNING_BITS} ;
6e9af7e4 624
f1f33818
PM
625 if (vec($mask, $Offsets{'all'}, 1)) {
626 $mask |= $Bits{'all'} ;
627 $mask |= $DeadBits{'all'} if vec($mask, $Offsets{'all'}+1, 1);
628 }
6e9af7e4
PM
629
630 push @_, 'all' unless @_;
631
632 foreach my $word ( @_ ) {
633 if ($word eq 'FATAL') {
634 $fatal = 1;
635 $no_fatal = 0;
636 }
637 elsif ($word eq 'NONFATAL') {
638 $fatal = 0;
639 $no_fatal = 1;
640 }
641 elsif ($catmask = $Bits{$word}) {
642 $mask |= $catmask ;
643 $mask |= $DeadBits{$word} if $fatal ;
644 $mask &= ~($DeadBits{$word}|$All) if $no_fatal ;
645 }
646 else
647 { Croaker("Unknown warnings category '$word'")}
648 }
649
650 ${^WARNING_BITS} = $mask ;
599cee73
PM
651}
652
6e9af7e4
PM
653sub unimport
654{
599cee73 655 shift;
6e9af7e4
PM
656
657 my $catmask ;
d3a7d8c7 658 my $mask = ${^WARNING_BITS} ;
6e9af7e4 659
d3a7d8c7 660 if (vec($mask, $Offsets{'all'}, 1)) {
f1f33818 661 $mask |= $Bits{'all'} ;
d3a7d8c7
GS
662 $mask |= $DeadBits{'all'} if vec($mask, $Offsets{'all'}+1, 1);
663 }
6e9af7e4
PM
664
665 push @_, 'all' unless @_;
666
667 foreach my $word ( @_ ) {
668 if ($word eq 'FATAL') {
669 next;
670 }
671 elsif ($catmask = $Bits{$word}) {
672 $mask &= ~($catmask | $DeadBits{$word} | $All);
673 }
674 else
675 { Croaker("Unknown warnings category '$word'")}
676 }
677
678 ${^WARNING_BITS} = $mask ;
599cee73
PM
679}
680
9df0f64f
MK
681my %builtin_type; @builtin_type{qw(SCALAR ARRAY HASH CODE REF GLOB LVALUE Regexp)} = ();
682
7e6d00f8 683sub __chk
599cee73 684{
d3a7d8c7
GS
685 my $category ;
686 my $offset ;
7e6d00f8 687 my $isobj = 0 ;
d3a7d8c7
GS
688
689 if (@_) {
690 # check the category supplied.
691 $category = shift ;
9df0f64f
MK
692 if (my $type = ref $category) {
693 Croaker("not an object")
694 if exists $builtin_type{$type};
695 $category = $type;
7e6d00f8
PM
696 $isobj = 1 ;
697 }
d3a7d8c7 698 $offset = $Offsets{$category};
c3186b65 699 Croaker("Unknown warnings category '$category'")
d3a7d8c7
GS
700 unless defined $offset;
701 }
702 else {
0ca4541c 703 $category = (caller(1))[0] ;
d3a7d8c7 704 $offset = $Offsets{$category};
c3186b65 705 Croaker("package '$category' not registered for warnings")
d3a7d8c7
GS
706 unless defined $offset ;
707 }
708
0ca4541c 709 my $this_pkg = (caller(1))[0] ;
7e6d00f8
PM
710 my $i = 2 ;
711 my $pkg ;
712
713 if ($isobj) {
714 while (do { { package DB; $pkg = (caller($i++))[0] } } ) {
715 last unless @DB::args && $DB::args[0] =~ /^$category=/ ;
716 }
717 $i -= 2 ;
718 }
719 else {
4f527b71 720 $i = _error_loc(); # see where Carp will allocate the error
7e6d00f8
PM
721 }
722
0ca4541c 723 my $callers_bitmask = (caller($i))[9] ;
7e6d00f8
PM
724 return ($callers_bitmask, $offset, $i) ;
725}
726
4f527b71
AS
727sub _error_loc {
728 require Carp::Heavy;
729 goto &Carp::short_error_loc; # don't introduce another stack frame
730}
731
7e6d00f8
PM
732sub enabled
733{
c3186b65 734 Croaker("Usage: warnings::enabled([category])")
7e6d00f8
PM
735 unless @_ == 1 || @_ == 0 ;
736
737 my ($callers_bitmask, $offset, $i) = __chk(@_) ;
738
739 return 0 unless defined $callers_bitmask ;
d3a7d8c7
GS
740 return vec($callers_bitmask, $offset, 1) ||
741 vec($callers_bitmask, $Offsets{'all'}, 1) ;
599cee73
PM
742}
743
d3a7d8c7 744
e476b1b5
GS
745sub warn
746{
c3186b65 747 Croaker("Usage: warnings::warn([category,] 'message')")
d3a7d8c7 748 unless @_ == 2 || @_ == 1 ;
d3a7d8c7 749
7e6d00f8
PM
750 my $message = pop ;
751 my ($callers_bitmask, $offset, $i) = __chk(@_) ;
09e96b99 752 require Carp;
8becbb3b 753 Carp::croak($message)
d3a7d8c7
GS
754 if vec($callers_bitmask, $offset+1, 1) ||
755 vec($callers_bitmask, $Offsets{'all'}+1, 1) ;
8becbb3b 756 Carp::carp($message) ;
e476b1b5
GS
757}
758
7e6d00f8
PM
759sub warnif
760{
c3186b65 761 Croaker("Usage: warnings::warnif([category,] 'message')")
7e6d00f8
PM
762 unless @_ == 2 || @_ == 1 ;
763
764 my $message = pop ;
765 my ($callers_bitmask, $offset, $i) = __chk(@_) ;
7e6d00f8 766
0ca4541c 767 return
7e6d00f8
PM
768 unless defined $callers_bitmask &&
769 (vec($callers_bitmask, $offset, 1) ||
770 vec($callers_bitmask, $Offsets{'all'}, 1)) ;
771
09e96b99 772 require Carp;
8becbb3b 773 Carp::croak($message)
7e6d00f8
PM
774 if vec($callers_bitmask, $offset+1, 1) ||
775 vec($callers_bitmask, $Offsets{'all'}+1, 1) ;
776
8becbb3b 777 Carp::carp($message) ;
7e6d00f8 778}
0d658bf5 779
599cee73 7801;