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