#!/usr/bin/perl -w
# See copyright, etc in below POD section.
######################################################################

require 5.005;
use lib 'blib/arch';
use lib 'blib/lib';
use lib '.';

use Getopt::Long;
use IO::File;
use Pod::Usage;

use Verilog::Preproc;
use Verilog::Getopt;
use strict;
use vars qw ($Debug $VERSION);

$VERSION = '3.210';

######################################################################
# main

$Debug = 0;
my $opt_output_filename = undef;
my $opt_blank=1;
my @opt_files;
my @opt_pp_flags;

autoflush STDOUT 1;
autoflush STDERR 1;

# Option parsing
my $Opt = new Verilog::Getopt();
@ARGV = $Opt->parameter(@ARGV);
Getopt::Long::config ("no_auto_abbrev");
if (! GetOptions (
		  "help"	=> \&usage,
		  "debug"	=> \&debug,
		  "o=s"		=> \$opt_output_filename,
		  "blank!"	=> \$opt_blank,
		  "comment!"	=> sub { push @opt_pp_flags, (keep_comments=>$_[1]); },
		  "line!"	=> sub { push @opt_pp_flags, (line_directives=>$_[1]); },
		  "pedantic!"	=> sub { push @opt_pp_flags, (pedantic=>$_[1]); },
		  "simple!"	=> sub { if ($_[1]) {
		      push @opt_pp_flags, (keep_comments=>0,
					   line_directives=>0,
					   );
		      $opt_blank=0;
		  } },
		  "version"	=> sub { print "Version $VERSION\n"; exit(0); },
		  "<>"		=> \&parameter,
		  )) {
    die "%Error: Bad usage, try 'vppreproc --help'\n";
}

if (!@opt_files) {
    die "%Error: vppreproc: No input filenames specified.\n";
}

my $fh = IO::File->new;
if ($opt_output_filename) {
    $fh->open(">$opt_output_filename") or die "%Error: $! $opt_output_filename\n";
} else {
    $fh->open(">-") or die;
}

my $vp = Verilog::Preproc->new(@opt_pp_flags,
			       options=>$Opt,);

$vp->debug($Debug) if $Debug;
foreach my $file (@opt_files) {
    $vp->open($file);
    while (defined (my $line = $vp->getline())) {
	next if !$opt_blank && $line =~ /^\s*[\n]?$/;
	print $fh $line;
    }
}

exit (0);

######################################################################

sub usage {
    print "Version $VERSION\n";
    pod2usage(-verbose=>2, -exitval => 2);
    exit (1);
}

sub debug {
    $Debug = 1;
}

sub parameter {
    my $param = shift;
    if ($param =~ /^--?/) {
	die "%Error: vppreproc: Unknown parameter: $param\n";
    } else {
	push @opt_files, $param;
    }
}

######################################################################
######################################################################
######################################################################

__END__

=pod

=head1 NAME

vppreproc - Preprocess Verilog code using verilog-perl

=head1 SYNOPSIS

  vppreproc --help
  vppreproc [verilog_options] [-o filename] [verilog_files.v...]

=head1 DESCRIPTION

Vppreproc reads the Verilog files passed on the command line and outputs
preprocessed output to standard out or the filename passed with B<-p>.

Note vppreproc was named vppp until release 3.100, so if you're looking for
vppp, this is the right replacement.  The vppp name conflicted with another
non-Verilog related tool.

=head1 VERILOG ARGUMENTS

The following arguments are compatible with GCC, VCS and most Verilog
programs.

=over 4

=item +define+I<var>+I<value>
=item -DI<var>=I<value>

Defines the given preprocessor symbol.

=item -f I<file>

Read the specified file, and act as if all text inside it was
specified as command line parameters.

=item +incdir+I<dir>
=item -II<dir>

Add the directory to the list of directories that should be searched
for include directories or libraries.

=item +libext+I<ext>+I<ext>...

Specify the extensions that should be used for finding modules.  If for
example module I<x> is referenced, look in I<x>.I<ext>.

=item -y I<dir>

Add the directory to the list of directories that should be searched
for include directories or libraries.

=back

=head1 VPPREPROC ARGUMENTS

=over 4

=item --help

Displays this message and program version and exits.

=item --o I<file>

Use the given filename for output instead of stdout.

=item --noblank

Removes empty lines from the output.  Should be used with --noline, as if
correct line numbers are needed, blank lines must be preserved for proper
accounting by the program reading the output of vppreproc.

=item --nocomment

Remove comments.

=item --noline

Remove `line directives.

=item --pedantic

Rigorously obey the Verilog spec.  This disables the `__FILE__ and
`__LINE__ features, and may disable other features that are not specified
in the approved language reference manual. Defaults false.

=item --simple

Requests simple output, an alias for --noline, --nocomment and --noblank.

=item --version

Displays program version and exits.

=back

=head1 LANGUAGE EXTENSIONS

Vppreproc supports the preprocessing constructs defined in the Verilog 2001
and SystemVerilog 2005 standards.

The following additional constructs may be added to your Verilog code.

=over 4

=item `__FILE__

The __FILE__ define expands to the current filename as a string, like C++'s
__FILE__.  This is in the draft SystemVerilog 2009 standard (but supported
by Verilog-Perl since 2004!)

=item `__LINE__

The __LINE__ define expands to the current line number, like C++'s __LINE__.
This is in the draft SystemVerilog 2009 standard (but supported by
Verilog-Perl since 2004!)

=item `error I<string>

This will report an error when encountered, like C++'s #error.

=back

=head1 DISTRIBUTION

Verilog-Perl is part of the L<http://www.veripool.org/> free Verilog EDA
software tool suite.  The latest version is available from CPAN and from
L<http://www.veripool.org/verilog-perl>.

Copyright 2000-2009 by Wilson Snyder.  This package is free software; you
can redistribute it and/or modify it under the terms of either the GNU
Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.

=head1 AUTHORS

Wilson Snyder <wsnyder@wsnyder.org>

=head1 SEE ALSO

L<Verilog-Perl>,
L<Verilog::Getopt>,
L<Verilog::Preproc>

=cut
######################################################################
