X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=warnings.pl;h=9149f691949cd5fe6bb0743b5b9509c65eafc98e;hb=696235b60874be65fe029a39969f44a0133ec2f8;hp=791beed35367d8f97892551a32ab3f11dd307ae1;hpb=d5a71f3055c3a1145f32dafabd5c3bba8ef27f4d;p=p5sagit%2Fp5-mst-13.2.git diff --git a/warnings.pl b/warnings.pl index 791beed..9149f69 100644 --- a/warnings.pl +++ b/warnings.pl @@ -1,5 +1,8 @@ #!/usr/bin/perl + +$VERSION = '1.00'; + BEGIN { push @INC, './lib'; } @@ -24,7 +27,6 @@ my $tree = { 'reserved' => DEFAULT_OFF, 'digit' => DEFAULT_OFF, 'parenthesis' => DEFAULT_OFF, - 'deprecated' => DEFAULT_OFF, 'printf' => DEFAULT_OFF, 'prototype' => DEFAULT_OFF, 'qw' => DEFAULT_OFF, @@ -34,6 +36,7 @@ my $tree = { 'debugging' => DEFAULT_ON, 'malloc' => DEFAULT_ON, }, + 'deprecated' => DEFAULT_OFF, 'void' => DEFAULT_OFF, 'recursion' => DEFAULT_OFF, 'redefine' => DEFAULT_OFF, @@ -44,8 +47,6 @@ my $tree = { 'regexp' => DEFAULT_OFF, 'glob' => DEFAULT_OFF, 'y2k' => DEFAULT_OFF, - 'chmod' => DEFAULT_OFF, - 'umask' => DEFAULT_OFF, 'untie' => DEFAULT_OFF, 'substr' => DEFAULT_OFF, 'taint' => DEFAULT_OFF, @@ -104,7 +105,7 @@ sub mkRange for ($i = 1 ; $i < @a; ++ $i) { - $out[$i] = ".." + $out[$i] = ".." if $a[$i] == $a[$i - 1] + 1 && $a[$i] + 1 == $a[$i + 1] ; } @@ -130,9 +131,9 @@ sub printTree print $prefix . "|\n" ; print $prefix . "+- $k" ; if (ref $v) - { + { print " " . "-" x ($max - length $k ) . "+\n" ; - printTree ($v, $prefix . "|" , $max + $indent - 1) + printTree ($v, $prefix . "|" , $max + $indent - 1) } else { print "\n" } @@ -142,9 +143,9 @@ sub printTree ########################################################################### -sub mkHex +sub mkHexOct { - my ($max, @a) = @_ ; + my ($f, $max, @a) = @_ ; my $mask = "\x00" x $max ; my $string = "" ; @@ -152,14 +153,29 @@ sub mkHex vec($mask, $_, 1) = 1 ; } - #$string = unpack("H$max", $mask) ; - #$string =~ s/(..)/\x$1/g; foreach (unpack("C*", $mask)) { - $string .= '\x' . sprintf("%2.2x", $_) ; + if ($f eq 'x') { + $string .= '\x' . sprintf("%2.2x", $_) + } + else { + $string .= '\\' . sprintf("%o", $_) + } } return $string ; } +sub mkHex +{ + my($max, @a) = @_; + return mkHexOct("x", $max, @a); +} + +sub mkOct +{ + my($max, @a) = @_; + return mkHexOct("o", $max, @a); +} + ########################################################################### if (@ARGV && $ARGV[0] eq "tree") @@ -169,8 +185,8 @@ if (@ARGV && $ARGV[0] eq "tree") exit ; } -#unlink "warnings.h"; -#unlink "lib/warnings.pm"; +unlink "warnings.h"; +unlink "lib/warnings.pm"; open(WARN, ">warnings.h") || die "Can't create warnings.h: $!\n"; open(PM, ">lib/warnings.pm") || die "Can't create lib/warnings.pm: $!\n"; @@ -207,6 +223,10 @@ $index = $offset ; #@{ $list{"all"} } = walk ($tree) ; walk ($tree) ; +die < 255 ; +Too many warnings categories -- max is 255 + rewrite packWARN* & unpackWARN* macros +EOM $index *= 2 ; my $warn_size = int($index / 8) + ($index % 8 != 0) ; @@ -221,6 +241,9 @@ print WARN tab(5, '#define WARNsize'), "$warn_size\n" ; #print WARN tab(5, '#define WARN_ALLstring'), '"', ('\377' x $warn_size) , "\"\n" ; print WARN tab(5, '#define WARN_ALLstring'), '"', ('\125' x $warn_size) , "\"\n" ; print WARN tab(5, '#define WARN_NONEstring'), '"', ('\0' x $warn_size) , "\"\n" ; +my $WARN_TAINTstring = mkOct($warn_size, map $_ * 2, @{ $list{'taint'} }); + +print WARN tab(5, '#define WARN_TAINTstring'), qq["$WARN_TAINTstring"\n] ; print WARN <<'EOM'; @@ -230,11 +253,6 @@ print WARN <<'EOM'; #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 || \ @@ -248,6 +266,23 @@ print WARN <<'EOM'; isWARN_on(PL_curcop->cop_warnings, y) ) ) \ || (isLEXWARN_off && PL_dowarn & G_WARN_ON) ) +#define ckWARN3(x,y,z) \ + ( (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) || \ + isWARN_on(PL_curcop->cop_warnings, z) ) ) \ + || (isLEXWARN_off && PL_dowarn & G_WARN_ON) ) + +#define ckWARN4(x,y,z,t) \ + ( (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) || \ + isWARN_on(PL_curcop->cop_warnings, z) || \ + isWARN_on(PL_curcop->cop_warnings, t) ) ) \ + || (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 && \ @@ -259,6 +294,39 @@ print WARN <<'EOM'; (isWARN_on(PL_curcop->cop_warnings, x) || \ isWARN_on(PL_curcop->cop_warnings, y) ) ) ) +#define ckWARN3_d(x,y,z) \ + (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) || \ + isWARN_on(PL_curcop->cop_warnings, z) ) ) ) + +#define ckWARN4_d(x,y,z,t) \ + (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) || \ + isWARN_on(PL_curcop->cop_warnings, z) || \ + isWARN_on(PL_curcop->cop_warnings, t) ) ) ) + +#define packWARN(a) (a ) +#define packWARN2(a,b) ((a) | (b)<<8 ) +#define packWARN3(a,b,c) ((a) | (b)<<8 | (c) <<16 ) +#define packWARN4(a,b,c,d) ((a) | (b)<<8 | (c) <<16 | (d) <<24) + +#define unpackWARN1(x) ((x) & 0xFF) +#define unpackWARN2(x) (((x) >>8) & 0xFF) +#define unpackWARN3(x) (((x) >>16) & 0xFF) +#define unpackWARN4(x) (((x) >>24) & 0xFF) + +#define ckDEAD(x) \ + ( ! specialWARN(PL_curcop->cop_warnings) && \ + ( isWARNf_on(PL_curcop->cop_warnings, WARN_ALL) || \ + isWARNf_on(PL_curcop->cop_warnings, unpackWARN1(x)) || \ + isWARNf_on(PL_curcop->cop_warnings, unpackWARN2(x)) || \ + isWARNf_on(PL_curcop->cop_warnings, unpackWARN3(x)) || \ + isWARNf_on(PL_curcop->cop_warnings, unpackWARN4(x)))) + /* end of file warnings.h */ EOM @@ -289,9 +357,9 @@ foreach $k (sort keys %list) { my $v = $list{$k} ; my @list = sort { $a <=> $b } @$v ; - print PM tab(4, " '$k'"), '=> "', - # mkHex($warn_size, @list), - mkHex($warn_size, map $_ * 2 , @list), + print PM tab(4, " '$k'"), '=> "', + # mkHex($warn_size, @list), + mkHex($warn_size, map $_ * 2 , @list), '", # [', mkRange(@list), "]\n" ; } @@ -303,9 +371,9 @@ foreach $k (sort keys %list) { my $v = $list{$k} ; my @list = sort { $a <=> $b } @$v ; - print PM tab(4, " '$k'"), '=> "', - # mkHex($warn_size, @list), - mkHex($warn_size, map $_ * 2 + 1 , @list), + print PM tab(4, " '$k'"), '=> "', + # mkHex($warn_size, @list), + mkHex($warn_size, map $_ * 2 + 1 , @list), '", # [', mkRange(@list), "]\n" ; } @@ -327,6 +395,8 @@ __END__ package warnings; +our $VERSION = '1.00'; + =head1 NAME warnings - Perl pragma to control optional warnings @@ -348,41 +418,101 @@ warnings - Perl pragma to control optional warnings warnings::warn("void", "some warning"); } + if (warnings::enabled($object)) { + warnings::warn($object, "some warning"); + } + + warnings::warnif("some warning"); + warnings::warnif("void", "some warning"); + warnings::warnif($object, "some warning"); + =head1 DESCRIPTION If no import list is supplied, all possible warnings are either enabled or disabled. -A number of functions are provided to assist module authors. +A number of functions are provided to assist module authors. =over 4 =item use warnings::register -Creates a new warnings category which has the same name as the module -where the call to the pragma is used. +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::enabled([$category]) +=item warnings::warn($category, $message) -Returns TRUE if the warnings category C<$category> is enabled in the -calling module. Otherwise returns FALSE. +Print C<$message> to STDERR. -If the parameter, C<$category>, isn't supplied, the current package name -will be used. +If the warnings category, C<$category>, has been set to "FATAL" in the +calling module then die. Otherwise return. -=item warnings::warn([$category,] $message) +=item warnings::warn($object, $message) -If the calling module has I set C<$category> to "FATAL", print -C<$message> to STDERR. -If the calling module has set C<$category> to "FATAL", print C<$message> -STDERR then die. +Print C<$message> to STDERR. -If the parameter, C<$category>, isn't supplied, the current package name -will be used. +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. +See L and L. =cut @@ -392,6 +522,12 @@ KEYWORDS $All = "" ; vec($All, $Offsets{'all'}, 2) = 3 ; +sub Croaker +{ + delete $Carp::CarpInternal{'warnings'}; + croak @_ ; +} + sub bits { my $mask ; my $catmask ; @@ -405,7 +541,7 @@ sub bits { $mask |= $DeadBits{$word} if $fatal ; } else - { croak("unknown warnings category '$word'")} + { Croaker("Unknown warnings category '$word'")} } return $mask ; @@ -413,44 +549,80 @@ sub bits { sub import { 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') ; } sub unimport { shift; my $mask = ${^WARNING_BITS} ; if (vec($mask, $Offsets{'all'}, 1)) { - $mask = $Bits{'all'} ; + $mask |= $Bits{'all'} ; $mask |= $DeadBits{'all'} if vec($mask, $Offsets{'all'}+1, 1); } - ${^WARNING_BITS} = $mask & ~ (bits(@_ ? @_ : 'all') | $All) ; + ${^WARNING_BITS} = $mask & ~ (bits('FATAL' => (@_ ? @_ : 'all')) | $All) ; } -sub enabled +sub __chk { - croak("Usage: warnings::enabled([category])") - unless @_ == 1 || @_ == 0 ; - local $Carp::CarpLevel = 1 ; my $category ; my $offset ; - my $callers_bitmask = (caller(1))[9] ; - return 0 unless defined $callers_bitmask ; - + my $isobj = 0 ; if (@_) { # check the category supplied. $category = shift ; + if (ref $category) { + Croaker ("not an object") + if $category !~ /^([^=]+)=/ ; + $category = $1 ; + $isobj = 1 ; + } $offset = $Offsets{$category}; - croak("unknown warnings category '$category'") + Croaker("Unknown warnings category '$category'") unless defined $offset; } else { - $category = (caller(0))[0] ; + $category = (caller(1))[0] ; $offset = $Offsets{$category}; - croak("package '$category' not registered for warnings") + Croaker("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 +{ + Croaker("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) ; } @@ -458,31 +630,34 @@ sub enabled sub warn { - croak("Usage: warnings::warn([category,] 'message')") + Croaker("Usage: warnings::warn([category,] 'message')") unless @_ == 2 || @_ == 1 ; - local $Carp::CarpLevel = 1 ; - my $category ; - my $offset ; - my $callers_bitmask = (caller(1))[9] ; - - if (@_ == 2) { - $category = shift ; - $offset = $Offsets{$category}; - croak("unknown warnings category '$category'") - unless defined $offset ; - } - else { - $category = (caller(0))[0] ; - $offset = $Offsets{$category}; - croak("package '$category' not registered for warnings") - unless defined $offset ; - } - my $message = shift ; - croak($message) + my $message = pop ; + my ($callers_bitmask, $offset, $i) = __chk(@_) ; + croak($message) if vec($callers_bitmask, $offset+1, 1) || vec($callers_bitmask, $Offsets{'all'}+1, 1) ; carp($message) ; } +sub warnif +{ + Croaker("Usage: warnings::warnif([category,] 'message')") + unless @_ == 2 || @_ == 1 ; + + my $message = pop ; + my ($callers_bitmask, $offset, $i) = __chk(@_) ; + + 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;