#! /usr/bin/perl -CSD
use strict;

my ($Prog, $Version) = ("w0-l-java", "2.0.3");
my $Java_class_id = "[A-Z]([a-z_0-9]\\w*)?";
my $Java_other_id = "[a-zA-Z]\\w*";
my $Java_id_list = "$Java_other_id(\\s*,\\s*$Java_other_id)*";
my %Res_words = ();
my %Special_words = ();
for ("abstract", "assert", "break", "case", "catch", "class", "const",
     "continue", "default", "do", "else", "extends", "false", "final",
     "finally", "for", "goto", "if", "implements", "import", "instanceof",
     "interface", "native", "new", "package", "private", "protected",
     "public", "return", "static", "strictfp", "super", "switch", 
     "synchronized", "this", "throw", "throws", "transient", "true", 
     "try", "volatile", "while") 
  { $Res_words{$_} = $Special_words{$_} = 1; }
my %Type_words = ();
for ("boolean", "byte", "char", "double", "float", "int", 
     "long", "short", "void")
  { $Type_words{$_} = $Special_words{$_} = 1; }
my $Enhance = 0;
PARAM:
while (@ARGV && $ARGV[0] =~ /^-/) { $_ = shift;
    /^-e$/ and do { $Enhance = "yes";  next PARAM; };
    /^-v$/ and do {
        print STDERR "This is $Prog (version $Version)\n";
        next PARAM; };
}
my $line = "";
while (<>) { 
    unless (/^code:(.*);$/) { print;  next; };
    chomp($line = $1);
    $_ = $line;  while ($_) {
    redo if s|^\s*//.*||;
redo if s|^\s*/\*.*\*/||;
redo if s:^\s*"(\\"|[^"])*"::;
redo if s:^\s*'(\\'|[^'])'::;
redo if s|^\s*package\s+[^;]*;||;
redo if s|^\s*import\s+[^;]*;||;
if (s|^\s*class\s+($Java_class_id)\b||o) {
    print "cdef:$1;\n";
    redo;
}
if (s|^\s*($Java_other_id)||o) { 
    my $id = $1;
    redo if $Res_words{$id};
if (s|^\s*\(||) {
    if ($id =~ /^$Java_class_id$/o) {
        print "cuse:$id;\n";
    } else {
        print "fuse:$id;\n" unless $Special_words{$id};  
    }
    redo;
}
if (s|^\s*($Java_other_id)\s*\(||o) {
    my $f = $1;
    print "cuse:$id;\n" if $id =~ /^$Java_class_id$/o;
    print "fdef:$f;\n" unless $Special_words{$f};
    if (s|^\s*[^)]*\)||) {
    local $_;
    foreach (split(/,/, $&)) {
        if (/($Java_other_id)\s+($Java_other_id)/o) {
            my $type = $1;
            my $id = $2;
            print "cuse:$type;\n" if $type =~ /^$Java_class_id$/o;
            print "vdef:$id;\n";
        }
    }
}
    redo;
}
if (($Type_words{$id}||$id=~/^$Java_class_id$/o) &&
        s|^\s*($Java_id_list)||o) {
    my $id_list = $1;
    print "cuse:$id;\n" if $id =~ /^$Java_class_id$/o;
    local $_;
    foreach (split(/[, ]+/, $id_list)) {
        print "vdef:$_;\n" unless $Special_words{$_};
    }
    redo;
}
if ($id =~ /^$Java_class_id$/o) {
    print "cuse:$id;\n";
} else {
    print "vuse:$id;\n" unless $Special_words{$id};
}
redo; 
}
s:^\s*[^A-Za-z_"'/]+:: or s:^\s*.?::;
}
    if ($Enhance) {
        $_ = $line;  while ($_) {
    if (s|^\s*//.*$||) {
    print "icode:$&;\n";  redo;
} elsif (s|^\s*/\*.*\*/||) {
    print "icode:$&;\n";  redo; 
}
if (s:^\s*"(\\"|[^"])*"::) {
    print "code:$&;\n";  redo;
}
if (s:^\s*'(\\'|[^'])'::) {
    print "code:$&;\n";  redo;
}
if (s|^(\s*)($Java_other_id)||o) {
    my ($space, $id) = ($1, $2);

    if ($id =~ /^$Java_class_id$/o) {
        print "code:$space;\n" if $space;
        print "bicode:$id;\n";
    } elsif ($Res_words{$id}) {
        print "code:$space;\n" if $space;
        print "bcode:$id;\n";
    } else {
        print "code:$space$id;\n";
    }
    redo;
}
s:^\s*[^A-Za-z_"'/]+:: or s:^\s*.?::;
print "code:$&;\n" if $&;
}
    } else {
        print "code:$line;\n";
    }
}
exit 0;

sub Error {
    &Message(@_);  
    &Tidy_up if defined &Tidy_up;
    exit 1;
}
sub Message {
    print STDERR "$Prog: ", shift, "\n";
    while (@_) {
        print STDERR " "x(2+length $Prog), shift, "\n";
    }
}
