X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/4673fc70de29ec9782a54acc86b498189e02a8e2..32f78baf72351c617b69c24c7d8f114f5fd2d837:/warnings.pl diff --git a/warnings.pl b/warnings.pl index c6f1313..4be4280 100644 --- a/warnings.pl +++ b/warnings.pl @@ -9,45 +9,57 @@ sub DEFAULT_ON () { 1 } sub DEFAULT_OFF () { 2 } my $tree = { - 'unsafe' => { 'untie' => DEFAULT_OFF, - 'substr' => DEFAULT_OFF, - 'taint' => DEFAULT_OFF, - 'signal' => DEFAULT_OFF, - 'closure' => DEFAULT_OFF, - 'overflow' => DEFAULT_OFF, - 'portable' => DEFAULT_OFF, - 'utf8' => DEFAULT_OFF, - } , - 'io' => { 'pipe' => DEFAULT_OFF, + +'all' => { + 'io' => { 'pipe' => DEFAULT_OFF, 'unopened' => DEFAULT_OFF, 'closed' => DEFAULT_OFF, 'newline' => DEFAULT_OFF, 'exec' => DEFAULT_OFF, - #'wr in in file'=> DEFAULT_OFF, }, - 'syntax' => { 'ambiguous' => DEFAULT_OFF, + 'syntax' => { 'ambiguous' => DEFAULT_OFF, 'semicolon' => DEFAULT_OFF, + 'precedence' => DEFAULT_OFF, 'bareword' => DEFAULT_OFF, 'reserved' => DEFAULT_OFF, - 'octal' => DEFAULT_OFF, 'digit' => DEFAULT_OFF, 'parenthesis' => DEFAULT_OFF, 'deprecated' => DEFAULT_OFF, 'printf' => DEFAULT_OFF, + 'prototype' => DEFAULT_OFF, + 'qw' => DEFAULT_OFF, }, - 'severe' => { 'inplace' => DEFAULT_ON, + 'severe' => { 'inplace' => DEFAULT_ON, 'internal' => DEFAULT_ON, 'debugging' => DEFAULT_ON, + 'malloc' => DEFAULT_ON, }, - 'void' => DEFAULT_OFF, - 'recursion' => DEFAULT_OFF, - 'redefine' => DEFAULT_OFF, - 'numeric' => DEFAULT_OFF, - 'uninitialized'=> DEFAULT_OFF, - 'once' => DEFAULT_OFF, - 'misc' => DEFAULT_OFF, + 'void' => DEFAULT_OFF, + 'recursion' => DEFAULT_OFF, + 'redefine' => DEFAULT_OFF, + 'numeric' => DEFAULT_OFF, + 'uninitialized' => DEFAULT_OFF, + 'once' => DEFAULT_OFF, + 'misc' => DEFAULT_OFF, + 'regexp' => DEFAULT_OFF, + 'glob' => DEFAULT_OFF, + 'y2k' => DEFAULT_OFF, + 'chmod' => DEFAULT_OFF, + 'umask' => DEFAULT_OFF, + 'untie' => DEFAULT_OFF, + 'substr' => DEFAULT_OFF, + 'taint' => DEFAULT_OFF, + 'signal' => DEFAULT_OFF, + 'closure' => DEFAULT_OFF, + 'overflow' => DEFAULT_OFF, + 'portable' => DEFAULT_OFF, + 'utf8' => DEFAULT_OFF, + 'exiting' => DEFAULT_OFF, + 'pack' => DEFAULT_OFF, + 'unpack' => DEFAULT_OFF, #'default' => DEFAULT_ON, - } ; + } +} ; ########################################################################### @@ -61,7 +73,7 @@ sub tab { my %list ; my %Value ; -my $index = 0 ; +my $index ; sub walk { @@ -103,6 +115,32 @@ sub mkRange } ########################################################################### +sub printTree +{ + my $tre = shift ; + my $prefix = shift ; + my $indent = shift ; + my ($k, $v) ; + + my $max = (sort {$a <=> $b} map { length $_ } keys %$tre)[-1] ; + + $prefix .= " " x $indent ; + foreach $k (sort keys %$tre) { + $v = $tre->{$k}; + print $prefix . "|\n" ; + print $prefix . "+- $k" ; + if (ref $v) + { + print " " . "-" x ($max - length $k ) . "+\n" ; + printTree ($v, $prefix . "|" , $max + $indent - 1) + } + else + { print "\n" } + } + +} + +########################################################################### sub mkHex { @@ -124,6 +162,12 @@ sub mkHex ########################################################################### +if (@ARGV && $ARGV[0] eq "tree") +{ + #print " all -+\n" ; + printTree($tree, " ", 4) ; + exit ; +} #unlink "warnings.h"; #unlink "lib/warnings.pm"; @@ -149,56 +193,20 @@ print WARN <<'EOM' ; #define G_WARN_ONCE 8 /* set if 'once' ever enabled */ #define G_WARN_ALL_MASK (G_WARN_ALL_ON|G_WARN_ALL_OFF) -#define WARN_STD Nullsv -#define WARN_ALL (Nullsv+1) /* use warnings 'all' */ -#define WARN_NONE (Nullsv+2) /* no warnings 'all' */ - -#define specialWARN(x) ((x) == WARN_STD || (x) == WARN_ALL || \ - (x) == WARN_NONE) - -#define ckDEAD(x) \ - ( ! specialWARN(PL_curcop->cop_warnings) && \ - IsSet(SvPVX(PL_curcop->cop_warnings), 2*x+1)) - -#define ckWARN(x) \ - ( (PL_curcop->cop_warnings != WARN_STD && \ - PL_curcop->cop_warnings != WARN_NONE && \ - (PL_curcop->cop_warnings == WARN_ALL || \ - IsSet(SvPVX(PL_curcop->cop_warnings), 2*x) ) ) \ - || (PL_curcop->cop_warnings == WARN_STD && PL_dowarn & G_WARN_ON) ) - -#define ckWARN2(x,y) \ - ( (PL_curcop->cop_warnings != WARN_STD && \ - PL_curcop->cop_warnings != WARN_NONE && \ - (PL_curcop->cop_warnings == WARN_ALL || \ - IsSet(SvPVX(PL_curcop->cop_warnings), 2*x) || \ - IsSet(SvPVX(PL_curcop->cop_warnings), 2*y) ) ) \ - || (PL_curcop->cop_warnings == WARN_STD && PL_dowarn & G_WARN_ON) ) - -#define ckWARN_d(x) \ - (PL_curcop->cop_warnings == WARN_STD || \ - PL_curcop->cop_warnings == WARN_ALL || \ - (PL_curcop->cop_warnings != WARN_NONE && \ - IsSet(SvPVX(PL_curcop->cop_warnings), 2*x) ) ) - -#define ckWARN2_d(x,y) \ - (PL_curcop->cop_warnings == WARN_STD || \ - PL_curcop->cop_warnings == WARN_ALL || \ - (PL_curcop->cop_warnings != WARN_NONE && \ - (IsSet(SvPVX(PL_curcop->cop_warnings), 2*x) || \ - IsSet(SvPVX(PL_curcop->cop_warnings), 2*y) ) ) ) - - -#define isLEXWARN_on (PL_curcop->cop_warnings != WARN_STD) -#define isLEXWARN_off (PL_curcop->cop_warnings == WARN_STD) -#define isWARN_ONCE (PL_dowarn & (G_WARN_ON|G_WARN_ONCE)) -#define isWARN_on(c,x) (IsSet(SvPVX(c), 2*(x))) +#define pWARN_STD Nullsv +#define pWARN_ALL (Nullsv+1) /* use warnings 'all' */ +#define pWARN_NONE (Nullsv+2) /* no warnings 'all' */ +#define specialWARN(x) ((x) == pWARN_STD || (x) == pWARN_ALL || \ + (x) == pWARN_NONE) EOM +my $offset = 0 ; + +$index = $offset ; +#@{ $list{"all"} } = walk ($tree) ; +walk ($tree) ; -$index = 0 ; -@{ $list{"all"} } = walk ($tree) ; $index *= 2 ; my $warn_size = int($index / 8) + ($index % 8 != 0) ; @@ -216,6 +224,41 @@ print WARN tab(5, '#define WARN_NONEstring'), '"', ('\0' x $warn_size) , "\"\n" print WARN <<'EOM'; +#define isLEXWARN_on (PL_curcop->cop_warnings != pWARN_STD) +#define isLEXWARN_off (PL_curcop->cop_warnings == pWARN_STD) +#define isWARN_ONCE (PL_dowarn & (G_WARN_ON|G_WARN_ONCE)) +#define isWARN_on(c,x) (IsSet(SvPVX(c), 2*(x))) +#define isWARNf_on(c,x) (IsSet(SvPVX(c), 2*(x)+1)) + +#define ckDEAD(x) \ + ( ! specialWARN(PL_curcop->cop_warnings) && \ + ( isWARNf_on(PL_curcop->cop_warnings, WARN_ALL) || \ + isWARNf_on(PL_curcop->cop_warnings, x))) + +#define ckWARN(x) \ + ( (isLEXWARN_on && PL_curcop->cop_warnings != pWARN_NONE && \ + (PL_curcop->cop_warnings == pWARN_ALL || \ + isWARN_on(PL_curcop->cop_warnings, x) ) ) \ + || (isLEXWARN_off && PL_dowarn & G_WARN_ON) ) + +#define ckWARN2(x,y) \ + ( (isLEXWARN_on && PL_curcop->cop_warnings != pWARN_NONE && \ + (PL_curcop->cop_warnings == pWARN_ALL || \ + isWARN_on(PL_curcop->cop_warnings, x) || \ + isWARN_on(PL_curcop->cop_warnings, y) ) ) \ + || (isLEXWARN_off && PL_dowarn & G_WARN_ON) ) + +#define ckWARN_d(x) \ + (isLEXWARN_off || PL_curcop->cop_warnings == pWARN_ALL || \ + (PL_curcop->cop_warnings != pWARN_NONE && \ + isWARN_on(PL_curcop->cop_warnings, x) ) ) + +#define ckWARN2_d(x,y) \ + (isLEXWARN_off || PL_curcop->cop_warnings == pWARN_ALL || \ + (PL_curcop->cop_warnings != pWARN_NONE && \ + (isWARN_on(PL_curcop->cop_warnings, x) || \ + isWARN_on(PL_curcop->cop_warnings, y) ) ) ) + /* end of file warnings.h */ EOM @@ -227,7 +270,19 @@ while () { print PM $_ ; } -$list{'all'} = [ 0 .. 8 * ($warn_size/2) - 1 ] ; +#$list{'all'} = [ $offset .. 8 * ($warn_size/2) - 1 ] ; + +#my %Keys = map {lc $Value{$_}, $_} keys %Value ; + +print PM "%Offsets = (\n" ; +foreach my $k (sort { $a <=> $b } keys %Value) { + my $v = lc $Value{$k} ; + $k *= 2 ; + print PM tab(4, " '$v'"), "=> $k,\n" ; +} + +print PM " );\n\n" ; + print PM "%Bits = (\n" ; foreach $k (sort keys %list) { @@ -255,6 +310,9 @@ foreach $k (sort keys %list) { } print PM " );\n\n" ; +print PM '$NONE = "', ('\0' x $warn_size) , "\";\n" ; +print PM '$LAST_BIT = ' . "$index ;\n" ; +print PM '$BYTES = ' . "$warn_size ;\n" ; while () { print PM $_ ; } @@ -281,13 +339,110 @@ warnings - Perl pragma to control optional warnings use warnings "all"; no warnings "all"; + use warnings::register; + if (warnings::enabled()) { + warnings::warn("some warning"); + } + + if (warnings::enabled("void")) { + warnings::warn("void", "some warning"); + } + + if (warnings::enabled($object)) { + warnings::warn($object, "some warning"); + } + + warnif("some warning"); + warnif("void", "some warning"); + warnif($object, "some warning"); + =head1 DESCRIPTION If no import list is supplied, all possible warnings are either enabled or disabled. -See L and L. +A number of functions are provided to assist module authors. + +=over 4 + +=item use warnings::register + +Creates a new warnings category with the same name as the package where +the call to the pragma is used. + +=item warnings::enabled() + +Use the warnings category with the same name as the current package. + +Return TRUE if that warnings category is enabled in the calling module. +Otherwise returns FALSE. + +=item warnings::enabled($category) + +Return TRUE if the warnings category, C<$category>, is enabled in the +calling module. +Otherwise returns FALSE. + +=item warnings::enabled($object) + +Use the name of the class for the object reference, C<$object>, as the +warnings category. + +Return TRUE if that warnings category is enabled in the first scope +where the object is used. +Otherwise returns FALSE. + +=item warnings::warn($message) + +Print C<$message> to STDERR. + +Use the warnings category with the same name as the current package. + +If that warnings category has been set to "FATAL" in the calling module +then die. Otherwise return. + +=item warnings::warn($category, $message) + +Print C<$message> to STDERR. + +If the warnings category, C<$category>, has been set to "FATAL" in the +calling module then die. Otherwise return. + +=item warnings::warn($object, $message) + +Print C<$message> to STDERR. + +Use the name of the class for the object reference, C<$object>, as the +warnings category. + +If that warnings category has been set to "FATAL" in the scope where C<$object> +is first used then die. Otherwise return. + + +=item warnings::warnif($message) + +Equivalent to: + + if (warnings::enabled()) + { warnings::warn($message) } + +=item warnings::warnif($category, $message) +Equivalent to: + + if (warnings::enabled($category)) + { warnings::warn($category, $message) } + +=item warnings::warnif($object, $message) + +Equivalent to: + + if (warnings::enabled($object)) + { warnings::warn($object, $message) } + +=back + +See L and L. =cut @@ -295,6 +450,8 @@ use Carp ; KEYWORDS +$All = "" ; vec($All, $Offsets{'all'}, 2) = 3 ; + sub bits { my $mask ; my $catmask ; @@ -303,12 +460,12 @@ sub bits { if ($word eq 'FATAL') { $fatal = 1; } - else { - if ($catmask = $Bits{$word}) { - $mask |= $catmask ; - $mask |= $DeadBits{$word} if $fatal ; - } + elsif ($catmask = $Bits{$word}) { + $mask |= $catmask ; + $mask |= $DeadBits{$word} if $fatal ; } + else + { croak("unknown warnings category '$word'")} } return $mask ; @@ -321,17 +478,107 @@ sub import { sub unimport { shift; - ${^WARNING_BITS} &= ~ bits(@_ ? @_ : 'all') ; + my $mask = ${^WARNING_BITS} ; + if (vec($mask, $Offsets{'all'}, 1)) { + $mask = $Bits{'all'} ; + $mask |= $DeadBits{'all'} if vec($mask, $Offsets{'all'}+1, 1); + } + ${^WARNING_BITS} = $mask & ~ (bits(@_ ? @_ : 'all') | $All) ; +} + +sub __chk +{ + my $category ; + my $offset ; + my $isobj = 0 ; + + if (@_) { + # check the category supplied. + $category = shift ; + if (ref $category) { + croak ("not an object") + if $category !~ /^([^=]+)=/ ;+ + $category = $1 ; + $isobj = 1 ; + } + $offset = $Offsets{$category}; + croak("unknown warnings category '$category'") + unless defined $offset; + } + else { + $category = (caller(1))[0] ; + $offset = $Offsets{$category}; + croak("package '$category' not registered for warnings") + unless defined $offset ; + } + + my $this_pkg = (caller(1))[0] ; + my $i = 2 ; + my $pkg ; + + if ($isobj) { + while (do { { package DB; $pkg = (caller($i++))[0] } } ) { + last unless @DB::args && $DB::args[0] =~ /^$category=/ ; + } + $i -= 2 ; + } + else { + for ($i = 2 ; $pkg = (caller($i))[0] ; ++ $i) { + last if $pkg ne $this_pkg ; + } + $i = 2 + if !$pkg || $pkg eq $this_pkg ; + } + + my $callers_bitmask = (caller($i))[9] ; + return ($callers_bitmask, $offset, $i) ; } sub enabled { - my $string = shift ; + croak("Usage: warnings::enabled([category])") + unless @_ == 1 || @_ == 0 ; + + my ($callers_bitmask, $offset, $i) = __chk(@_) ; + + return 0 unless defined $callers_bitmask ; + return vec($callers_bitmask, $offset, 1) || + vec($callers_bitmask, $Offsets{'all'}, 1) ; +} + - return 1 - if $bits{$string} && ${^WARNING_BITS} & $bits{$string} ; - - return 0 ; +sub warn +{ + croak("Usage: warnings::warn([category,] 'message')") + unless @_ == 2 || @_ == 1 ; + + my $message = pop ; + my ($callers_bitmask, $offset, $i) = __chk(@_) ; + local $Carp::CarpLevel = $i ; + croak($message) + if vec($callers_bitmask, $offset+1, 1) || + vec($callers_bitmask, $Offsets{'all'}+1, 1) ; + carp($message) ; } +sub warnif +{ + croak("Usage: warnings::warnif([category,] 'message')") + unless @_ == 2 || @_ == 1 ; + + my $message = pop ; + my ($callers_bitmask, $offset, $i) = __chk(@_) ; + local $Carp::CarpLevel = $i ; + + return + unless defined $callers_bitmask && + (vec($callers_bitmask, $offset, 1) || + vec($callers_bitmask, $Offsets{'all'}, 1)) ; + + croak($message) + if vec($callers_bitmask, $offset+1, 1) || + vec($callers_bitmask, $Offsets{'all'}+1, 1) ; + + carp($message) ; +} 1;