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