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