#!/usr/bin/perl
# ###
# PiMPx - the Perl-inclusive Macro Processor
# (c) 2001-2007 - Ask Solem <ask@0x61736b.net>
# All rights reserved.
#
#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License version 2 
#   as published by the Free Software Foundation.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program; if not, write to the Free Software
#   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# $Id: pimpx,v 1.4 2007/05/07 12:46:18 ask Exp $
# $Source: /opt/CVS/pimpx/bin/pimpx,v $
# $Author: ask $
# $HeadURL$
# $Revision: 1.4 $
# $Date: 2007/05/07 12:46:18 $
#####
use strict;
use warnings;

use vars qw($me $VERSION);
use Devel::PiMPx;
$VERSION = $Devel::PiMPx::VERSION;

# ### basename of myself.
$me = $0;
$me =~ s{.*/}{}xms;

my $pp = Devel::PiMPx->new(
    programname => $me,
);
$pp->no_lineno(1); # default on.

my $version = Version->new($Devel::PiMPx::VERSION);

# ###
# get filename from command arguments,
# and run the preprocessor.
my $file = _parseopts(@ARGV);
my $ret  = $pp->preprocess($file);
exit 0;

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

# ##### void _version(void)
# print version information.
#
sub _version {
	printf {*STDERR} "PiMPx - the Perl-inclusive Macro-Processor %s\n", $version->extended();
	print  {*STDERR} "Copyright 2001-2007 Ask Solem <ask\@0x61736b.net>\n";
}

# ##### void _usage(void)
# print usage information
#
sub _usage {
	print STDERR "Usage: $me {[-I/include|-Dvar|-Dvar=val|--debug|--lineno]] - {filename}|[-h|-V]}\n";
}

# #### char _parseopts(array argv)
# parse command line arguments and return the filename given.
#
sub _parseopts {
	my @argv = @_;
	my $file; # filename to return
	while ($_ = shift @argv) {
		if	(s/^-$//) {
			# ### 
			# if we get a "-" the rest of the arguments 
			# is the filename to process.
			return "@argv" if @argv;
		}
		elsif	(s/^-O//) {
			# ###
			# -Ofilename: redirect standard output to <filename>.
			#
			die "*** Missing filename as argument to -O\n"
			  unless $_;
			open OUTPUT, ">$_"
			  or die "*** $me: Error: Couldn't open $_: $!\n";
			*STDOUT=*OUTPUT;
		}
		elsif	(s/^(--version|-V)//) {
				# print version information
				_version();
				exit;
		}
		elsif	(s/^(--help|-h)//) {
				# print version and help
				_version();
				_usage();
				exit;
		}
		elsif	(s/^--debug//) {
				# print debugging information at runtime.
				$pp->debug(1);
				print STDERR "*** Debug option set\n";
		}
		elsif	(s/^(--no-lineno|-L)//) {
				# don't print #line comments.
				$pp->no_lineno(1);
				print STDERR "*** Don't print #line directives option set.\n" if $pp->debug;
		}
		elsif	(s/^(--lineno|-l)//) {
				# print #line comments
				$pp->no_lineno(0);
				print STDERR "*** Print #line directives option set.\n" if $pp->debug;
		}
		elsif	(s/^-I//) {
				# ### 
				# -Ipath: add path to @INC
				#
				die "*** Missing path as argument to -I\n" unless $_;
				print STDERR "*** New include path: $_\n" if $pp->debug;
				push @INC, $_;
		}
		elsif	(s/^-D//xms) {
				# ###
				# -Dvar(=value)?: Define value to variable.
				# if no value is given, variable is set to true (1).
				#
				if (/^(.+?)=(.+?)?$/xms) {
					next unless $2; # must have value if "=" character found.
					print STDERR "*** Variable $1 set to $2\n" if $pp->debug;
					$pp->_define("$1 $2");
				}
				else {
					print STDERR "*** Variable $_ defined\n" if $pp->debug;
					print "$@\n" if $@;
					$pp->define("$1 1");
				}
		}
		elsif	(not /^-/) {
				# ### 
				# this argument is our file if no dash character
				# is found at the start.
				$file = $_;
		}
	};
	if (! $file) {
		# ### print some help if no file given.
		_version();
		_usage();	
		END;
        exit;
	}
	return $file;
}

#--------- Version.pm ----------#
# ###
# Version.pm - kernel/gnome like version library
# (c) 1999-2007 Ask Solem <ask@0x61736b.net>
# All rights reserved.
#
#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License version 2
#   as published by the Free Software Foundation.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program; if not, write to the Free Software
#   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#####

package Version;
use Carp;
use Exporter;
use vars qw(%EXPORT_TAGS @EXPORT @EXPORT_OK @ISA);

@ISA = qw(@EXPORT @EXPORT_OK);

@EXPORT = qw();
@EXPORT_OK = qw(cmp_version);
%EXPORT_TAGS = ( all => qw(cmp_version) );

# ### Version new(char version)
# create new Version object with thre dotted version
# as argument.
#
sub new {
	my ($pkg, $version) = @_;
	my $self = {};
	bless $self, $pkg;
	$self->version($version);
	return $self;
};

# ### char version(char version)
# set version or get version currently set
#
sub version {
	my ($self, $version) = @_;
	# set version if we got version as argument.
	if($version) {
		($self->{MAJOR}, $self->{MINOR}, $self->{RELEA})
			= split('\.', $version);   
		$self->{VERSION} = $version;
	};
	return $self->{VERSION};
};

# ### accessors
sub major { $_[0]->{MAJOR} };
sub minor { $_[0]->{MINOR} };
sub relea { $_[0]->{RELEA} };

# ### char extended(void)
# get extended version information
#
sub extended {
	my $self = shift;
	my $su;
	# ### stable if even, unstable if odd.
	if($self->minor() % 2) {
		$su = "unstable";
	}
	else {
		$su = "stable";
	};
	return sprintf("%s (%s)", $self->version, $su);
};

# ### int check(char check_against, char operator)
# check current version against check_against with operator.
# example:
#	# ### check if version "1.1.0" is higher or equal to current version.
#	unless($version->check("1.1.0", ">=") {
#		die("Must have version higher than or equal to 1.1.0\n");
#	};
#
sub check {
	my($self, $check_against, $operator) = @_;
	# ###
	# operator can only be of the following characters:
	# >, <, =, !
	carp "Illegal characters in operator or missing operator."
		unless $operator =~ /^[\>\<\=\!]+$/;
	# ### 
	# remove the dots from the versions
	# i.e 2.4.0 and 2.2.0 becomes 240 and 220,
	# then we just check the two against the operator.
	$check_against =~ s/\.//g;
	my $version = $self->version();
	$version =~ tr/.//d;
	if(eval "return 1 if($check_against $operator $version)") {
		return 1;
	}
	else {
		return 0;
	};
};

# ### int check(char version1|Version version, version2);
# compare two versions. if first argument is reference to Version
# object it swaps version 1 with Version->version().
# returns equal, less than og higher than.
#
sub cmp_version {
	my($x, $y) = @_;
	my $version;
	if(ref $x) {
		# swap
		my $self = $x;	
		$x = $self->version();
	}
	$x =~ tr/.//d; $y =~ tr/.//d;	
	return ($x - $y);
}

__END__

=head1 NAME

pimpx - The Perl-inclusive Macro Processor

=head1 VERSION

This document describes PiMPx version 0.8.0.

=head1 SYNOPSIS

 pimpx {[-I/include|-Dvar|-Dvar=val|--debug|--lineno]] - {filename}|[-h|-V]}

=head1 DESCRIPTION

PiMPx is the Perl-inclusive Macro Processor.
It simplifies the management of bigger projects in Perl and can
be used in other languages that use lines beginning with "#" as comments.

=head1 SEE ALSO
 
L<perl>. L<Devel::PiMPx>

=head1 AUTHOR

Ask Solem E<lt>ask@0x61736b.netE<gt>

=head1 LICENSE AND COPYRIGHT

Copyright (c), 2007 Ask Solem C<< ask@0x61736b.net >>.

All rights reserved.

This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8.6 or,
at your option, any later version of Perl 5 you may have available.head1 DISCLAIMER OF WARRANTY                                            
                                                                         
BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE
SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE
STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE 
SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND  
PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE,
YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION.   
                                                                         
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY
COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE
SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO
LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR
THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER     
SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE    
POSSIBILITY OF SUCH DAMAGES.

=cut

