Platon Technologies
not logged in Login Registration
EnglishSlovak
open source software development celebrating 10 years of open source development! Saturday, April 20, 2024

File: [Platon] / platos / _scripts / colorgcc (download)

Revision 1.1.1.1 (vendor branch), Thu Feb 6 19:25:12 2003 UTC (21 years, 2 months ago) by rajo


Changes since 1.1: +0 -0 lines

Platon SDG office

#! /usr/bin/perl -w

#
# colorgcc
#
# Version: 1.3.2
#
# $Id: colorgcc,v 1.1.1.1 2003/02/06 19:25:12 rajo Exp $
#
# A wrapper to colorize the output from compilers whose messages
# match the "gcc" format.
#
# Requires the ANSIColor module from CPAN.
#
# Usage:
#
# In a directory that occurs in your PATH _before_ the directory
# where the compiler lives, create a softlink to colorgcc for
# each compiler you want to colorize:
#
#    g++ -> colorgcc
#    gcc -> colorgcc
#    cc  -> colorgcc
#    etc.
#
# That's it. When "g++" is invoked, colorgcc is run instead.
# colorgcc looks at the program name to figure out which compiler to run.
#
# The default settings can be overridden with ~/.colorgccrc.
# See the comments in the sample .colorgccrc for more information.
#
# Note:
#
# colorgcc will only emit color codes if:
# 
#    (1) Its STDOUT is a tty and
#    (2) the value of $TERM is not listed in the "nocolor" option.
#
# If colorgcc colorizes the output, the compiler's STDERR will be
# combined with STDOUT. Otherwise, colorgcc just passes the output from
# the compiler through without modification.
# 
# Author: Jamie Moyers <jmoyers@geeks.com>
# Started: April 20, 1999
# Licence: GNU Public License
#
# Credits:
#
#    I got the idea for this from a script called "color_cvs":
#       color_cvs .03   Adrian Likins <adrian@gimp.org> <adrian@redhat.com>
#
#    <seh4@ix.netcom.com> (Scott Harrington)
#       Much improved handling of compiler command line arguments.
#       exec compiler when not colorizing to preserve STDOUT, STDERR.
#       Fixed my STDIN kludge.
#       
#    <ecarotti@athena.polito.it> (Elias S. G. Carotti)
#       Corrected handling of text like -DPACKAGE=\"Package\"
#       Spotted return code bug.
#
#    <erwin@erwin.andreasen.org> (Erwin S. Andreasen)
#    <schurchi@ucsd.edu> (Steve Churchill)
#       Return code bug fixes.
#
#    <rik@kde.org> (Rik Hemsley)
#       Found STDIN bug.
#
# Changes:
#
# 1.3.2 Better handling of command line arguments to compiler.
#
#       If we aren't colorizing output, we just exec the compiler which
#       preserves the original STDOUT and STDERR.
#
#       Removed STDIN kludge. STDIN being passed correctly now.
# 
# 1.3.1 Added kludge to copy STDIN to the compiler's STDIN.
#
# 1.3.0 Now correctly returns (I hope) the return code of the compiler
#       process as its own.
# 
# 1.2.1 Applied patch to handle text similar to -DPACKAGE=\"Package\".
#
# 1.2.0 Added tty check. If STDOUT is not a tty, don't do color.
#
# 1.1.0 Added the "nocolor" option to turn off the color if the terminal type
#       ($TERM) is listed.
#
# 1.0.0 Initial Version

use Term::ANSIColor;
use IPC::Open3;

sub initDefaults
{
    $compilerPaths{"gcc"}   = "/usr/bin/gcc-2.96";
    $compilerPaths{"g++"}   = "/usr/bin/g++-2.96";
    $compilerPaths{"cc"}    = "/usr/bin/gcc-2.96";
    $compilerPaths{"c++"}   = "/usr/bin/g++-2.96";
    $compilerPaths{"make"}  = "/usr/bin/make";
    $compilerPaths{"latex"} = "/usr/bin/latex";

    $nocolor{"dumb"} = "true";

    $colors{"srcColor"}              = color("cyan");
    $colors{"introColor"}            = color("blue");

    $colors{"warningFileNameColor"}  = color("yellow");
    $colors{"warningNumberColor"}    = color("yellow");
    $colors{"warningMessageColor"}   = color("yellow");

    $colors{"errorFileNameColor"}    = color("bold red");
    $colors{"errorNumberColor"}      = color("bold red");
    $colors{"errorMessageColor"}     = color("bold red");

    $colors{"makeColor"}             = color("cyan");
    $colors{"makeSrcColor"}          = color("cyan");
    $colors{"makeEnterDirColor"}     = color("bold green");
    $colors{"makeLeaveDirColor"}     = color("green");
    $colors{"makeErrorMessageColor"} = color("bold red");

    $color{"latexWarningColor"}      = color("yellow");
    $color{"latexOverfullColor"}     = color("bold yellow");
    $color{"latexUnderfullColor"}    = color("bold yellow");

    # defined OK:
    $character{"e1"} = "á"; # 225 0xE1
    $character{"e9"} = "é"; # 233 0xE9
    $character{"ed"} = "í"; # 237 0xED
    $character{"a9"} = "µ"; # 181 0xB5
    $character{"f3"} = "ó"; # 243 0xF3
    $character{"b2"} = "¹"; # 185 0xB9
    $character{"b9"} = "¹"; # changed from ¼ 0Xbc
    $character{"fa"} = "ú"; # 250 0xFA
    $character{"fd"} = "ý"; # 253 0xFD
    $character{"ba"} = "¾"; # 190 0xBE
    $character{"91"} = "¦"; # 166 0xA6
    $character{"92"} = "©"; # 169 0xA9
    $character{"94"} = "«"; # 171 0xAB
    $character{"e4"} = "ä"; # 228 0xE4
    $character{"f4"} = "ô"; # 244 0xF4
    $character{"9a"} = "®"; # 174 0xAE
    $character{"af"} = "à"; # 224 0xE0
    $character{"b1"} = "¶"; # 182 0xB6
    $character{"a8"} = "å"; # 229 0xE5
    $character{"a2"} = "æ"; # 230 0xE6
    $character{"a3"} = "è"; # 232 0xE8
    $character{"a4"} = "ï"; # 239 0xEF
    $character{"a5"} = "ì"; # 236 0xEC
    $character{"ab"} = "ñ"; # ñ 0Xf1
    $character{"ac"} = "ò"; # ò 0Xf2
    $character{"f6"} = "ö"; # ö 0Xf6
    $character{"b0"} = "ø"; # ø 0Xf8
    $character{"b4"} = "»"; # » 0Xbb
    $character{"fc"} = "ü"; # ü 0Xfc
    $character{"c1"} = "Á"; # Á 0Xc1
    $character{"c4"} = "Ä"; # Ä 0Xc4
    $character{"82"} = "Æ"; # Æ 0Xc6
    $character{"83"} = "È"; # È 0Xc8
    $character{"84"} = "Ï"; # Ï 0Xcf
    $character{"c9"} = "É"; # É 0Xc9
    $character{"85"} = "Ì"; # Ì 0Xcc
    $character{"cd"} = "Í"; # Í 0Xcd
    $character{"88"} = "Å"; # Å 0Xc5
    $character{"89"} = "¥"; # ¥ 0Xa5
    $character{"8b"} = "Ñ"; # Ñ 0Xd1
    $character{"8c"} = "Ò"; # Ò 0Xd2
    $character{"d3"} = "Ó"; # Ó 0Xd3
    $character{"d4"} = "Ô"; # Ô 0Xd4
    $character{"8f"} = "À"; # À 0Xc0
    $character{"90"} = "Ø"; # Ø 0Xd8
    $character{"da"} = "Ú"; # Ú 0Xda
    $character{"dc"} = "Ü"; # Ü 0Xdc
    $character{"dd"} = "Ý"; # Ý 0Xdd
    $character{"99"} = "¬"; # ¬ 0Xac
}

sub loadPreferences
{
# Usage: loadPreferences("filename");

    my($filename) = @_;

    open(PREFS, "<$filename") || return;

    while(<PREFS>) {
        next if (m/^\#.*/);          # It's a comment.
        next if (!m/(.*):\s*(.*)/);  # It's not of the form "foo: bar".

        $option = $1;
        $value = $2;

        if ($option =~ m/cc|c\+\+|gcc|g\+\+|make|latex/) {
            $compilerPaths{$option} = $value;
        }
        elsif ($option eq "nocolor") {
            # The nocolor option lists terminal types, separated by
            # spaces, not to do color on.
            foreach $termtype (split(/\s+/, $value)) {
                $nocolor{$termtype} = "true";
            }
        }
        else {
            $colors{$option} = color($value);
        }
    }
    close(PREFS);
}

sub srcscan
{
# Usage: srcscan($text, $normalColor)
#    $text -- the text to colorize
#    $normalColor -- The escape sequence to use for non-source text.

# Looks for text between ` and ', and colors it srcColor.

    my($line, $normalColor) = @_;

    my($srcon) = color("reset") . $colors{"srcColor"};
    my($srcoff) = color("reset") . $normalColor;

    $line = $normalColor . $line;

    # This substitute replaces `foo' with `AfooB' where A is the escape
    # sequence that turns on the the desired source color, and B is the
    # escape sequence that returns to $normalColor.
    $line =~ s/\`(.*?)\'/\`$srcon$1$srcoff\'/g;

    print($line, color("reset"));
}

#
# Main program
#

# Set up default values for colors and compilers.
initDefaults();

# Read the configuration file, if there is one.
$configFile = $ENV{"HOME"} . "/.colorgccrc";
#$default_configFile = "/etc/colorgccrc";
$default_configFile = $ENV{"HOME"} . "/.colorgccrc";
if (-f $configFile) {
    loadPreferences($configFile);
} elsif (-f $default_configFile ) {
    loadPreferences($default_configFile)
}

# Figure out which compiler to invoke based on our program name.
$0 =~ m%.*/(.*)$%;
$progName = $1 || $0;

$compiler = $compilerPaths{$progName} || $compilerPaths{"gcc"};

# Get the terminal type. 
$terminal = $ENV{"TERM"} || "dumb";

# If it's in the list of terminal types not to color, or if
# we're writing to something that's not a tty, don't do color.
if (! -t STDOUT || $nocolor{$terminal}) {
    exec $compiler, @ARGV
        or die("Couldn't exec");
}

# Keep the pid of the compiler process so we can get its return
# code and use that as our return code.
$compiler_pid = open3('<&STDIN', \*COMPILEROUT, \*COMPILEROUT, $compiler, @ARGV);

sub diacritics_output($)
{
    my ($line) = @_;
    my $str = "";
    #printf("line = '$line'\n");

    while ($line =~ m/\^\^([0-9a-f][0-9a-f])/) {
        $field = $1 || "";
        $str = $character{"$field"} || sprintf "%c", hex("0x$field");
        #print ("pred substit. line = '$line'\nsubst = 's/\^\^$field/$str/g;'\n");
        $line =~ s/\^\^$field/$str/g;
        #print ("po substit. line = '$line'\n");
    }
    print("$line");
}

sub diacritics($)
{
    my ($line) = @_;
    $_ = <COMPILEROUT>;
    while (length($_) == 80) {
        s/[\r\n]$//g;
        $line = $line . $_;
        $_ = <COMPILEROUT>;
    }
    $line = $line . $_;

    diacritics_output($line);    
}

# Colorize the output from the compiler.
while(<COMPILEROUT>)
{
    if (m/^LaTeX Warning:.*/) { # output from LaTeX
        print($color{"latexWarningColor"}, $_, color("reset"));
    }
    elsif (m/^! Missing number.*/) {
        print($color{"latexWarningColor"}, $_, color("reset"));
    }
    elsif (m/Overfull \\[hv]box.*/) {
        print($color{"latexOverfullColor"}, $_, color("reset"));
        diacritics("");
    }
    elsif (m/^Underfull \\[hv]box.*/) {
        print($color{"latexUnderfullColor"}, $_, color("reset"));
        diacritics("");
    }
    elsif (m/^l\.([0-9]+)( .*)/) {
        $field1 = $1 || "";
        $field2 = $2 || "";
        diacritics_output("l." . $colors{"errorNumberColor"} . "$field1" . color("reset") . "$field2\n");
    }
    elsif (m/\.\.\.$/) {
        diacritics_output($_);
    }
    elsif (m/^(make[^:]*):(.*)$/) { # output from 'make'
        $field1 = $1 || "";
        $field2 = $2 || "";
        print($colors{"makeColor"}, "$field1:", color("reset"));
        if ($field2 =~ m/Entering directory/) {
            print($colors{"makeEnterDirColor"}, "$field2\n", color("reset")); 
        }
        elsif ($field2 =~ m/Leaving directory/) {
            print($colors{"makeLeaveDirColor"}, "$field2\n", color("reset")); 
        }
        elsif ($field2 =~ m/^[ \t]*\*\*\*|Entering an unknown directory|Leaving an unknown directory/) {
            print($colors{"makeErrorMessageColor"}, "$field2\n", color("reset")); 
        }
        elsif ($field2 =~ m/^([ \t]*\[.*\]) (Error [^ ]*) (\(.*\))$/) {
            print($colors{"makeErrorMessageColor"}, "$1 $2 ",
                $colors{"makeSrcColor"}, "$3\n", color("reset")); 
        }
        else {
            print("$field2\n", color("reset"));
        }
    }
    elsif (m/^(.*?):([0-9]+):(.*)$/) { # filename:lineno:message
        $field1 = $1 || "";
        $field2 = $2 || "";
        $field3 = $3 || "";

        if ($field3 =~ m/\s+warning:.*/) {
            # Warning
            print($colors{"warningFileNameColor"}, "$field1:", color("reset"));
            print($colors{"warningNumberColor"}, "$field2:", color("reset"));
            srcscan($field3, $colors{"warningMessageColor"});
        }
        else {
            # Error
            print($colors{"errorFileNameColor"}, "$field1:", color("reset"));
            print($colors{"errorNumberColor"}, "$field2:", color("reset"));
            srcscan($field3, $colors{"errorMessageColor"});
        }
        print("\n");
    }
    elsif (m/^(.*?):(.+):$/) { # filename:message:
        # No line number, treat as an "introductory" line of text.
        srcscan($_, $colors{"introColor"});
    }
    else { # Anything else.        
        # Doesn't seem to be a warning or an error. Print normally.
        print(color("reset"), $_);
    }
}

# Get the return code of the compiler and exit with that.
waitpid($compiler_pid, 0);
exit ($? >> 8);


Platon Group <platon@platon.org> http://platon.org/
Copyright © 2002-2006 Platon Group
Site powered by Metafox CMS
Go to Top