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

my ($Prog, $Version) = ("w0-l-c", "2.0.3");
my $C_id = "[A-Za-z_]\\w*";
my $C_id_list = "$C_id(([*, ]*$C_id)*)";
my %Res_words = ();
my %Special_words = ();
for ("auto", "break", "case", "const", "continue", "default", "do", 
    "else", "enum", "extern", "for", "goto", "if", "register",
    "return", "sizeof", "static", "struct", "switch", "typedef",
    "union", "volatile", "while") 
  { $Res_words{$_} = $Special_words{$_} = 1; }
my %Type_words = ();
for ("char", "double", "float", "int", "long", "short",
    "unsigned", "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|^#.*$||;
redo if s|^\s*/\*.*\*/||;
redo if s:^\s*"(\\"|[^"])*"::;
redo if s:^\s*'(\\'|[^'])'::;
if (s|^\s*($C_id)||o) { 
    my $id = $1;
    redo if $Res_words{$id};
if (s|^\s*\(||) {
    print "fuse:$id;\n" unless $Special_words{$id};  
    redo;
}
if (s|^\s*[* ]*($C_id)\s*\(||o) {
    print "fdef:$1;\n" unless $Special_words{$1};
    redo;
}
if (s|^\s*[* ]*($C_id_list)||o) {
    local $_;
    foreach (split(/[*, ]+/, $1)) {
        print "vdef:$_;\n" unless $Special_words{$_};
    }
    redo;
}
print "vuse:$id;\n" unless $Special_words{$id};
redo; 
}
s:^\s*[^A-Za-z_"'/]+:: or s:^\s*.?::;
}
    if ($Enhance) {
        $_ = $line;  /^#/ and do { print "bicode:$_;\n"; next; };
while ($_) {
    if (s|^\s*/\*.*\*/||) {
    print "icode:$&;\n";  redo;
}
if (s:^\s*"(\\"|[^"])*"::) {
    print "code:$&;\n";  redo;
}
if (s:^\s*'(\\'|[^'])'::) {
    print "code:$&;\n";  redo;
}
if (s|^(\s*)($C_id)||o) {
    if ($Res_words{$2}) {
        print "code:$1;\n" if $1;
        print "bcode:$2;\n";
    } else {
        print "code:$&;\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";
    }
}
