Integrate with Sarathy.
Jarkko Hietaniemi [Sun, 5 Mar 2000 20:15:34 +0000 (20:15 +0000)]
p4raw-id: //depot/cfgperl@5555

12 files changed:
MANIFEST
lib/Pod/InputObjects.pm
lib/Term/ANSIColor.pm [new file with mode: 0644]
opcode.h
opcode.pl
pod/perldelta.pod
pod/perlfunc.pod
pp.c
t/comp/proto.t
t/lib/ansicolor.t [new file with mode: 0755]
toke.c
utils/perlbug.PL

index 636318c..3701f0c 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -651,6 +651,7 @@ lib/SelectSaver.pm  Enforce proper select scoping
 lib/SelfLoader.pm      Load functions only on demand
 lib/Shell.pm           Make AUTOLOADed system() calls
 lib/Symbol.pm          Symbol table manipulation routines
+lib/Term/ANSIColor.pm  Perl module supporting termcap usage
 lib/Term/Cap.pm                Perl module supporting termcap usage
 lib/Term/Complete.pm   A command completion subroutine
 lib/Term/ReadLine.pm   Stub readline library
@@ -1193,6 +1194,7 @@ t/io/print.t              See if print commands work
 t/io/read.t            See if read works
 t/io/tell.t            See if file seeking works
 t/lib/abbrev.t         See if Text::Abbrev works
+t/lib/ansicolor.t      See if Term::ANSIColor works
 t/lib/anydbm.t         See if AnyDBM_File works
 t/lib/attrs.t          See if attrs works with C<sub : attrs>
 t/lib/autoloader.t     See if AutoLoader works
index 2f89cb9..9029f8c 100644 (file)
@@ -522,7 +522,7 @@ sub _set_child2parent_links {
    my ($self, @children) = @_;
    ## Make sure any sequences know who their parent is
    for (@children) {
-      next unless (ref || ref eq 'SCALAR');
+      next if (!ref || ref eq 'SCALAR');
       if ($_->isa('Pod::InteriorSequence') or $_->can('nested')) {
           $_->nested($self);
       }
diff --git a/lib/Term/ANSIColor.pm b/lib/Term/ANSIColor.pm
new file mode 100644 (file)
index 0000000..e7a2157
--- /dev/null
@@ -0,0 +1,307 @@
+# Term::ANSIColor -- Color screen output using ANSI escape sequences.
+# $Id: ANSIColor.pm,v 1.1 1997/12/10 20:05:29 eagle Exp $
+#
+# Copyright 1996, 1997 by Russ Allbery <rra@stanford.edu>
+#                     and Zenin <zenin@best.com>
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the same terms as Perl itself.
+
+############################################################################
+# Modules and declarations
+############################################################################
+
+package Term::ANSIColor;
+require 5.001;
+
+use strict;
+use vars qw(@ISA @EXPORT %EXPORT_TAGS $VERSION $AUTOLOAD %attributes
+            $AUTORESET $EACHLINE);
+
+use Exporter ();
+@ISA         = qw(Exporter);
+@EXPORT      = qw(color colored);
+%EXPORT_TAGS = (constants => [qw(CLEAR RESET BOLD UNDERLINE UNDERSCORE BLINK
+                                 REVERSE CONCEALED BLACK RED GREEN YELLOW
+                                 BLUE MAGENTA CYAN WHITE ON_BLACK ON_RED
+                                 ON_GREEN ON_YELLOW ON_BLUE ON_MAGENTA
+                                 ON_CYAN ON_WHITE)]);
+Exporter::export_ok_tags ('constants');
+    
+($VERSION = (split (' ', q$Revision: 1.1 $ ))[1]) =~ s/\.(\d)$/.0$1/;
+
+
+############################################################################
+# Internal data structures
+############################################################################
+
+%attributes = ('clear'      => 0,
+               'reset'      => 0,
+               'bold'       => 1,
+               'underline'  => 4,
+               'underscore' => 4,
+               'blink'      => 5,
+               'reverse'    => 7,
+               'concealed'  => 8,
+
+               'black'      => 30,   'on_black'   => 40, 
+               'red'        => 31,   'on_red'     => 41, 
+               'green'      => 32,   'on_green'   => 42, 
+               'yellow'     => 33,   'on_yellow'  => 43, 
+               'blue'       => 34,   'on_blue'    => 44, 
+               'magenta'    => 35,   'on_magenta' => 45, 
+               'cyan'       => 36,   'on_cyan'    => 46, 
+               'white'      => 37,   'on_white'   => 47);
+
+
+############################################################################
+# Implementation (constant form)
+############################################################################
+
+# Time to have fun!  We now want to define the constant subs, which are
+# named the same as the attributes above but in all caps.  Each constant sub
+# needs to act differently depending on whether $AUTORESET is set.  Without
+# autoreset:
+#
+#   BLUE "text\n"  ==>  "\e[34mtext\n"
+#
+# If $AUTORESET is set, we should instead get:
+#
+#   BLUE "text\n"  ==>  "\e[34mtext\n\e[0m"
+#
+# The sub also needs to handle the case where it has no arguments correctly.
+# Maintaining all of this as separate subs would be a major nightmare, as
+# well as duplicate the %attributes hash, so instead we define an AUTOLOAD
+# sub to define the constant subs on demand.  To do that, we check the name
+# of the called sub against the list of attributes, and if it's an all-caps
+# version of one of them, we define the sub on the fly and then run it.
+sub AUTOLOAD {
+    my $sub;
+    ($sub = $AUTOLOAD) =~ s/^.*:://;
+    my $attr = $attributes{lc $sub};
+    if ($sub =~ /^[A-Z_]+$/ && defined $attr) {
+        $attr = "\e[" . $attr . 'm';
+        eval qq {
+            sub $AUTOLOAD {
+                if (\$AUTORESET && \@_) {
+                    '$attr' . "\@_" . "\e[0m";
+                } else {
+                    ('$attr' . "\@_");
+                }
+            }
+        };
+        goto &$AUTOLOAD;
+    } else {
+        die "undefined subroutine &$AUTOLOAD called";
+    }
+}
+
+
+############################################################################
+# Implementation (attribute string form)
+############################################################################
+
+# Return the escape code for a given set of color attributes.
+sub color {
+    my @codes = map { split } @_;
+    my $attribute = '';
+    foreach (@codes) {
+        $_ = lc $_;
+        unless (defined $attributes{$_}) {
+            require Carp;
+            Carp::croak ("Invalid attribute name $_");
+        }
+        $attribute .= $attributes{$_} . ';';
+    }
+    chop $attribute;
+    ($attribute ne '') ? "\e[${attribute}m" : undef;
+}
+
+# Given a string and a set of attributes, returns the string surrounded by
+# escape codes to set those attributes and then clear them at the end of the
+# string.  If $EACHLINE is set, insert a reset before each occurrence of the
+# string $EACHLINE and the starting attribute code after the string
+# $EACHLINE, so that no attribute crosses line delimiters (this is often
+# desirable if the output is to be piped to a pager or some other program).
+sub colored {
+    my $string = shift;
+    if (defined $EACHLINE) {
+        my $attr = color (@_);
+        join '', 
+            map { $_ && $_ ne $EACHLINE ? $attr . $_ . "\e[0m" : $_ }
+                split (/(\Q$EACHLINE\E)/, $string);
+    } else {
+        color (@_) . $string . "\e[0m";
+    }
+}
+
+
+############################################################################
+# Module return value and documentation
+############################################################################
+
+# Ensure we evaluate to true.
+1;
+__END__
+
+=head1 NAME
+
+Term::ANSIColor - Color screen output using ANSI escape sequences
+
+=head1 SYNOPSIS
+
+    use Term::ANSIColor;
+    print color 'bold blue';
+    print "This text is bold blue.\n";
+    print color 'reset';
+    print "This text is normal.\n";
+    print colored ("Yellow on magenta.\n", 'yellow on_magenta');
+    print "This text is normal.\n";
+
+    use Term::ANSIColor qw(:constants);
+    print BOLD, BLUE, "This text is in bold blue.\n", RESET;
+
+    use Term::ANSIColor qw(:constants);
+    $Term::ANSIColor::AUTORESET = 1;
+    print BOLD BLUE "This text is in bold blue.\n";
+    print "This text is normal.\n";
+
+=head1 DESCRIPTION
+
+This module has two interfaces, one through color() and colored() and the
+other through constants.
+    
+color() takes any number of strings as arguments and considers them to be
+space-separated lists of attributes.  It then forms and returns the escape
+sequence to set those attributes.  It doesn't print it out, just returns
+it, so you'll have to print it yourself if you want to (this is so that
+you can save it as a string, pass it to something else, send it to a file
+handle, or do anything else with it that you might care to).
+
+The recognized attributes (all of which should be fairly intuitive) are
+clear, reset, bold, underline, underscore, blink, reverse, concealed,
+black, red, green, yellow, blue, magenta, on_black, on_red, on_green,
+on_yellow, on_blue, on_magenta, on_cyan, and on_white.  Case is not
+significant.  Underline and underscore are equivalent, as are clear and
+reset, so use whichever is the most intuitive to you.  The color alone
+sets the foreground color, and on_color sets the background color.
+
+Note that attributes, once set, last until they are unset (by sending the
+attribute "reset").  Be careful to do this, or otherwise your attribute will
+last after your script is done running, and people get very annoyed at
+having their prompt and typing changed to weird colors.
+
+As an aid to help with this, colored() takes a scalar as the first
+argument and any number of attribute strings as the second argument and
+returns the scalar wrapped in escape codes so that the attributes will be
+set as requested before the string and reset to normal after the string.
+Normally, colored() just puts attribute codes at the beginning and end of
+the string, but if you set $Term::ANSIColor::EACHLINE to some string,
+that string will be considered the line delimiter and the attribute will
+be set at the beginning of each line of the passed string and reset at the
+end of each line.  This is often desirable if the output is being sent to
+a program like a pager that can be confused by attributes that span lines.
+Normally you'll want to set $Term::ANSIColor::EACHLINE to C<"\n"> to use
+this feature.
+
+Alternately, if you import C<:constants>, you can use the constants CLEAR,
+RESET, BOLD, UNDERLINE, UNDERSCORE, BLINK, REVERSE, CONCEALED, BLACK, RED,
+GREEN, YELLOW, BLUE, MAGENTA, ON_BLACK, ON_RED, ON_GREEN, ON_YELLOW,
+ON_BLUE, ON_MAGENTA, ON_CYAN, and ON_WHITE directly.  These are the same
+as color('attribute') and can be used if you prefer typing:
+
+    print BOLD BLUE ON_WHITE "Text\n", RESET;
+
+to
+
+    print colored ("Text\n", 'bold blue on_white');
+
+When using the constants, if you don't want to have to remember to add the
+C<, RESET> at the end of each print line, you can set
+$Term::ANSIColor::AUTORESET to a true value.  Then, the display mode will
+automatically be reset if there is no comma after the constant.  In other
+words, with that variable set:
+
+    print BOLD BLUE "Text\n";
+
+will reset the display mode afterwards, whereas:
+
+    print BOLD, BLUE, "Text\n";
+
+will not.
+
+The subroutine interface has the advantage over the constants interface in
+that only 2 soubrutines are exported into your namespace, verses 22 in the
+constants interface.  On the flip side, the constants interface has the
+advantage of better compile time error checking, since misspelled names of
+colors or attributes in calls to color() and colored() won't be caught
+until runtime whereas misspelled names of constants will be caught at
+compile time.  So, polute your namespace with almost two dozen subrutines
+that you may not even use that oftin, or risk a silly bug by mistyping an
+attribute.  Your choice, TMTOWTDI after all.
+
+=head1 DIAGNOSTICS
+
+=over 4
+
+=item Invalid attribute name %s
+
+You passed an invalid attribute name to either color() or colored().
+
+=item Identifier %s used only once: possible typo
+
+You probably mistyped a constant color name such as:
+
+    print FOOBAR "This text is color FOOBAR\n";
+
+It's probably better to always use commas after constant names in order to
+force the next error.
+
+=item No comma allowed after filehandle
+
+You probably mistyped a constant color name such as:
+
+    print FOOBAR, "This text is color FOOBAR\n";
+
+Generating this fatal compile error is one of the main advantages of using
+the constants interface, since you'll immediately know if you mistype a
+color name.
+
+=item Bareword %s not allowed while "strict subs" in use
+
+You probably mistyped a constant color name such as:
+
+    $Foobar = FOOBAR . "This line should be blue\n";
+
+or:
+
+    @Foobar = FOOBAR, "This line should be blue\n";
+
+This will only show up under use strict (another good reason to run under
+use strict).
+
+=back
+
+=head1 RESTRICTIONS
+
+It would be nice if one could leave off the commas around the constants
+entirely and just say:
+
+    print BOLD BLUE ON_WHITE "Text\n" RESET;
+
+but the syntax of Perl doesn't allow this.  You need a comma after the
+string.  (Of course, you may consider it a bug that commas between all the
+constants aren't required, in which case you may feel free to insert
+commas unless you're using $Term::ANSIColor::AUTORESET.)
+
+For easier debuging, you may prefer to always use the commas when not
+setting $Term::ANSIColor::AUTORESET so that you'll get a fatal compile
+error rather than a warning.
+
+=head1 AUTHORS
+
+Original idea (using constants) by Zenin (zenin@best.com), reimplemented
+using subs by Russ Allbery (rra@stanford.edu), and then combined with the
+original idea by Russ with input from Zenin.
+
+=cut
index ce88940..646add4 100644 (file)
--- a/opcode.h
+++ b/opcode.h
@@ -1643,12 +1643,12 @@ EXT U32 PL_opargs[] = {
        0x00001a44,     /* dump */
        0x00001a44,     /* goto */
        0x00013644,     /* exit */
-       0x0132c81c,     /* open */
+       0x0052c81c,     /* open */
        0x0001d614,     /* close */
        0x000cc814,     /* pipe_op */
        0x0000d61c,     /* fileno */
        0x0001361c,     /* umask */
-       0x0000d604,     /* binmode */
+       0x0012c804,     /* binmode */
        0x0042e855,     /* tie */
        0x0000f614,     /* untie */
        0x0000f604,     /* tied */
index 59b039b..29ef602 100755 (executable)
--- a/opcode.pl
+++ b/opcode.pl
@@ -605,13 +605,13 @@ exit              exit                    ck_fun          ds%     S?
 
 # I/O.
 
-open           open                    ck_fun          ist@    F S? S?
+open           open                    ck_fun          ist@    F S? L
 close          close                   ck_fun          is%     F?
 pipe_op                pipe                    ck_fun          is@     F F
 
 fileno         fileno                  ck_fun          ist%    F
 umask          umask                   ck_fun          ist%    S?
-binmode                binmode                 ck_fun          s%      F
+binmode                binmode                 ck_fun          s@      F S?
 
 tie            tie                     ck_fun          idms@   R S L
 untie          untie                   ck_fun          is%     R
index 05481e1..052162b 100644 (file)
@@ -1746,7 +1746,18 @@ For details and examples, please see L<Pod::Usage>.
 
 =item Pod::Text and Pod::Man
 
-[TODO - Russ Allbery <rra@stanford.edu>]
+Pod::Text has been rewritten to use Pod::Parser.  While pod2text() is
+still available for backwards compatibility, the module now has a new
+preferred interface.  See L<Pod::Text> for the details.  The new Pod::Text
+module is easily subclassed for tweaks to the output, and two such
+subclasses (Pod::Text::Termcap for man-page-style bold and underlining
+using termcap information, and Pod::Text::Color for markup with ANSI color
+sequences) are now standard.
+
+pod2man has been turned into a module, Pod::Man, which also uses
+Pod::Parser.  In the process, several outstanding bugs related to quotes
+in section headers, quoting of code escapes, and nested lists have been
+fixed.  pod2man is now a wrapper script around this module.
 
 =item SDBM_File
 
@@ -1769,6 +1780,12 @@ no longer requires syslog.ph to exist.
 Sys::Hostname now uses XSUBs to call the C library's gethostname() or
 uname() if they exist.
 
+=item Term::ANSIColor
+
+Term::ANSIColor is a very simple module to provide easy and readable
+access to the ANSI color and highlighting escape sequences, supported by
+most ANSI terminal emulators.  It is now included standard.
+
 =item Time::Local
 
 The timelocal() and timegm() functions used to silently return bogus
index 758b573..650a00a 100644 (file)
@@ -439,6 +439,8 @@ does.  Returns true if it succeeded, false otherwise.  NAME should be a
 packed address of the appropriate type for the socket.  See the examples in
 L<perlipc/"Sockets: Client/Server Communication">.
 
+=item binmode FILEHANDLE, DISCIPLINE
+
 =item binmode FILEHANDLE
 
 Arranges for FILEHANDLE to be read or written in "binary" mode on
@@ -2538,7 +2540,7 @@ to be converted into a file mode, for example. (Although perl will
 automatically convert strings into numbers as needed, this automatic
 conversion assumes base 10.)
 
-=item open FILEHANDLE,MODE,EXPR
+=item open FILEHANDLE,MODE,LIST
 
 =item open FILEHANDLE,EXPR
 
diff --git a/pp.c b/pp.c
index 4210bd6..300b20f 100644 (file)
--- a/pp.c
+++ b/pp.c
@@ -426,7 +426,7 @@ PP(pp_prototype)
                        seen_question = 1;
                        str[n++] = ';';
                    }
-                   else if (seen_question) 
+                   else if (n && str[0] == ';' && seen_question) 
                        goto set;       /* XXXX system, exec */
                    if ((oa & (OA_OPTIONAL - 1)) >= OA_AVREF 
                        && (oa & (OA_OPTIONAL - 1)) <= OA_HVREF) {
index 6381fac..ee17088 100755 (executable)
@@ -384,7 +384,7 @@ print "ok ", $i++, "\n";
 print "not " if defined prototype('CORE::system');
 print "ok ", $i++, "\n";
 
-print "# CORE::open => ($p)\nnot " if ($p = prototype('CORE::open')) ne '*;$;$';
+print "# CORE::open => ($p)\nnot " if ($p = prototype('CORE::open')) ne '*;$@';
 print "ok ", $i++, "\n";
 
 print "# CORE:Foo => ($p), \$@ => `$@'\nnot " 
diff --git a/t/lib/ansicolor.t b/t/lib/ansicolor.t
new file mode 100755 (executable)
index 0000000..3e16dce
--- /dev/null
@@ -0,0 +1,73 @@
+#!./perl
+
+BEGIN {
+    chdir 't' if -d 't';
+    unshift @INC, '../lib';
+}
+
+# Test suite for the Term::ANSIColor Perl module.  Before `make install' is
+# performed this script should be runnable with `make test'.  After `make
+# install' it should work as `perl test.pl'.
+
+############################################################################
+# Ensure module can be loaded
+############################################################################
+
+BEGIN { $| = 1; print "1..7\n" }
+END   { print "not ok 1\n" unless $loaded }
+use Term::ANSIColor qw(:constants color colored);
+$loaded = 1;
+print "ok 1\n";
+
+
+############################################################################
+# Test suite
+############################################################################
+
+# Test simple color attributes.
+if (color ('blue on_green', 'bold') eq "\e[34;42;1m") {
+    print "ok 2\n";
+} else {
+    print "not ok 2\n";
+}
+
+# Test colored.
+if (colored ("testing", 'blue', 'bold') eq "\e[34;1mtesting\e[0m") {
+    print "ok 3\n";
+} else {
+    print "not ok 3\n";
+}
+
+# Test the constants.
+if (BLUE BOLD "testing" eq "\e[34m\e[1mtesting") {
+    print "ok 4\n";
+} else {
+    print "not ok 4\n";
+}
+
+# Test AUTORESET.
+$Term::ANSIColor::AUTORESET = 1;
+if (BLUE BOLD "testing" eq "\e[34m\e[1mtesting\e[0m\e[0m") {
+    print "ok 5\n";
+} else {
+    print "not ok 5\n";
+}
+
+# Test EACHLINE.
+$Term::ANSIColor::EACHLINE = "\n";
+if (colored ("test\n\ntest", 'bold')
+    eq "\e[1mtest\e[0m\n\n\e[1mtest\e[0m") {
+    print "ok 6\n";
+} else {
+    print colored ("test\n\ntest", 'bold'), "\n";
+    print "not ok 6\n";
+}
+
+# Test EACHLINE with multiple trailing delimiters.
+$Term::ANSIColor::EACHLINE = "\r\n";
+if (colored ("test\ntest\r\r\n\r\n", 'bold')
+    eq "\e[1mtest\ntest\r\e[0m\r\n\r\n") {
+    print "ok 7\n";
+} else {
+    print "not ok 7\n";
+}
diff --git a/toke.c b/toke.c
index 805c9e9..61d6bb4 100644 (file)
--- a/toke.c
+++ b/toke.c
@@ -3984,7 +3984,7 @@ Perl_yylex(pTHX)
            LOP(OP_BIND,XTERM);
 
        case KEY_binmode:
-           UNI(OP_BINMODE);
+           LOP(OP_BINMODE,XTERM);
 
        case KEY_bless:
            LOP(OP_BLESS,XTERM);
index f46564e..f6280d2 100644 (file)
@@ -37,8 +37,8 @@ my @patches;
 while (<PATCH_LEVEL>) {
     last if /^\s*}/;
     chomp;
-    s/^\s+,?"?//;
-    s/"?,?$//;
+    s/^\s+,?\s*"?//;
+    s/"?\s*,?$//;
     s/(['\\])/\\$1/g;
     push @patches, $_ unless $_ eq 'NULL';
 }