This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
cosmetic OS/2 patches
[perl5.git] / warnings.pl
index 0e74f3d..e5ac703 100644 (file)
@@ -1,5 +1,8 @@
 #!/usr/bin/perl
 
+
+$VERSION = '1.00';
+
 BEGIN {
   push @INC, './lib';
 }
@@ -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";
 
@@ -221,6 +237,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';
 
@@ -289,9 +308,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 +322,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 +346,8 @@ __END__
 
 package warnings;
 
+our $VERSION = '1.00';
+
 =head1 NAME
 
 warnings - Perl pragma to control optional warnings
@@ -348,37 +369,97 @@ warnings - Perl pragma to control optional warnings
         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.
 
-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)
 
-=item warnings::enabled([$category])
+Use the name of the class for the object reference, C<$object>, as the
+warnings category.
 
-Returns TRUE if the warnings category C<$category> is enabled in the
-calling module.  Otherwise returns FALSE.
+Return TRUE if that warnings category is enabled in the first scope
+where the object is used.
+Otherwise returns FALSE.
 
-If the parameter, C<$category>, isn't supplied, the current package name
-will be used.
+=item warnings::warn($message)
 
-=item warnings::warn([$category,] $message)
+Print C<$message> to STDERR.
 
-If the calling module has I<not> 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.
+Use the warnings category with the same name as the current package.
 
-If the parameter, C<$category>, isn't supplied, the current package name
-will be used.
+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
 
@@ -405,7 +486,7 @@ sub bits {
            $mask |= $DeadBits{$word} if $fatal ;
        }
        else
-          { croak("unknown warnings category '$word'")}  
+          { croak("Unknown warnings category '$word'")}
     }
 
     return $mask ;
@@ -413,44 +494,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) {
+            croak ("not an object")
+                if $category !~ /^([^=]+)=/ ;
+           $category = $1 ;
+            $isobj = 1 ;
+        }
         $offset = $Offsets{$category};
-        croak("unknown warnings category '$category'")
+        croak("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")
            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
+{
+    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) ;
 }
@@ -460,29 +577,34 @@ sub warn
 {
     croak("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(@_) ;
+    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;