#! /usr/local/bin/perl

#
#	GNU Copyleft (c) 2000 Qualis Design Corporation
#
#	World Wide Web: http://www.qualis.com	
#
# Description:
#       Fix the automatically-generated *.vrh files by
#       prepending any included file in the original *.vr file.
#       and virtual port declarations.
#
# Author:      $Author: Janick Bergeron $
# Revision:    $Revision: 1.2 $
#

sub usage
{
    print STDERR <<USAGE;

Usage: $0 {fname.vrh}

Insert the missing #include directives and virtual port declarations
in an automatically generated *.vrh file from the original *.vr file.

USAGE

    exit(1);
}

#
# Parse the command-line options
#
require "getopts.pl";
&usage if !&Getopts("hl:n:s:") || $opt_h || !@ARGV;

#
# Fix all files specified on the command line
#
$rc = 0;
foreach $file (@ARGV) {

    # Infer the name of the original source file
    if ($file !~ m#^(.*/)?([^/]+)\.vrh$#) {
	print STDERR "ERROR: $file is not a *.vrh file.\n";
	next;
    }
    $source = "$1$2.vr";
    $new    = "$1.$2.vr";

    # The original source better exist!
    if (! -e $source) {
	print STDERR "ERROR: $source does not exist.\n";
	next;
    }

    # Can we read it?
    if (!open(SRC, "< $source")) {
	print STDERR "ERROR: Cannot open $source for reading: $!\n";
	next;
    }

    # Grab all of the include directive and
    # virtual port declarations we can find
    # in the original source file
    $line = 0;
    @include = ();
    while ($_ = <SRC>) {
	$line++;

	# Is it an include directive ?
	if (m/^\s*#\s*include\s*(\S+)\s*$/) {
	    push(@include, $1);
	    next;
	}

	# Strip comments
	s#//.*$##;

	# Is it a virtual port declaration ?
	if (s/^\s*port\s+(\S+)//) {
	    $port = $1;
	    # Find the '{'
	    while (!s/^\s*\{\s*//) {
		# Slurp the next line
		if (!($_ = <SRC>)) {
		    print STDERR "ERROR: $source: Unexpected end-of-file\n";
		    exit(0);
		}
		# Strip comments
		s#//.*$##;
		$line++;
	    }
	    # Parse the semi-colon separated list of signals
	    # until we reach a '}'
	    @signals = ();
	    while ($_ !~ m/^\s*\}/) {
		# Is the line empty?
		if (m/^\s*$/) {
		    # Slurp the next line
		    if (!($_ = <SRC>)) {
			print STDERR "ERROR: $source: Unexpected end-of-file\n";
			exit(0);
		    }
		    # Strip comments
		    s#//.*$##;
		    $line++;
		    next;
		}
		if (!s/\s*(\w+)\s*(;\s*)?//) {
		    print STDERR "ERROR: $source, line $line: Invalid port syntax: $_";
		    exit(0);
		}
		push(@signals, $1);
	    }
	    push(@ports, join(":", $port, @signals));
	    next;
	}
    }
    close(SRC);

    # Open the original *.vrh file, and the new one
    if (!open(VRH, "< $file")) {
	print STDERR "ERROR: Cannot open $file for reading: $!\n";
	next;
    }
    if (!open(NEW, "> $new")) {
	print STDERR "ERROR: Cannot open $new for writing: $!\n";
	close(VRH);
	next;
    }

    # Copy the old file into the new file, until
    # we reach the '#define ..._VRH' symbol to control
    # multiple inclusion of the *.vrh file.
    while ($_ = <VRH>) {
	print NEW $_;
	last if m/^\s*#\s*define.*_VRH\s*$/;
    }

    # Insert the needed #include directives
    print NEW "\n\n// start - Added by $0, ", '$Revision: 1.2 $', ":\n\n";
    foreach $include (@include) {
	print NEW "#include $include\n";
    }
    print NEW "\n";

    # Insert the needed port declarations
    foreach $port (@ports) {
        ($name, @signals) = split(/:/, $port);
	print NEW "port $name\n{\n   ",
                  join(";\n   ", @signals),
                  ";\n}\n";
    }
    print NEW "\n//  end  - Added by $0, ", '$Revision: 1.2 $', ":\n\n\n";

    # Copy the rest of the file
    while ($_ = <VRH>) {
	print NEW $_;
    }
    close(NEW);
    close(VRH);

    # Replace the original *.vrh file with the new one
    if (!unlink($file)) {
	print STDERR "ERROR: Cannot replace $file: $!\n";
	next;
    }

    if (!rename("$new", $file)) {
	print STDERR "ERROR: Cannot rename $new to $file: $!\n";
	next;
    }
}

exit($rc);

