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

# This is foomatic-ppd-options, a program which will print out the
# options specified by a PPD file.
#
# foomatic-ppd-options [file*]
#  reads one or more PPD files from the specified file or
#  standard input.  If present, PPD information is separated by
#  lines starting with Printer: .  This makes it compatible with
#  the LPRng 'lpc ppd' command:
#    lpc ppd | foomatic-ppd-options

use Foomatic::Defaults;
use Foomatic::DB;
use Data::Dumper;
use FileHandle;

$0 =~ m!/([^/]+)\s*$!;
my $progname = ($1 || $0);

sub help {
    print STDERR <<EOF;
$progname [-d=debuglevel][files]
  reads one or more PPD files from the specified file or
  standard input.  If present, PPD information is separated by
  lines starting with Printer: .  This makes it compatible with
  the LPRng 'lpc ppd' command:
    lpc ppd | foomatic-ppd-options
  
 -h            - printes help message
 -d debuglevel - sets debugging level (0 is 0ff)
EOF
    exit 1;
}
# Read out the program name with which we were called, but discard the path

my $debug = 0;

# We use the library Getopt::Long here, so that we can have more than
# one "-o" option on one command line.

my( $opt_h, $opt_d );

use Getopt::Long;
Getopt::Long::Configure("no_ignore_case");
GetOptions(
	   "d=i"   => \$opt_d,         # Help!
	   "h"   => \$opt_h,         # Help!
	   "help"=> \$opt_h) || help();

help() if $opt_h;
$debug = $opt_d if $opt_d;

sub getppdinfo( $ $ );
if( @ARGV ){
	while( @ARGV ){
		my $file = shift @ARGV;
		print STDERR "file $file\n" if $debug;
		my $fd = new FileHandle "<$file";
		if( not $fd ){
			die( "$progname: cannot open '$file' - $!\n" );
			next;
		}
		getppdinfo($fd, $file);
		close($fd);
	}
} else {
	getppdinfo( \*STDIN, "STDIN" );
}

exit 0;

my $key;
sub order_by_key{$a->{$key} cmp $b->{$key}};

sub getppdinfo( $ $ ){
	my( $fd, $name ) = @_;
	my @ppd = <$fd>;
	close( $fd );
	print "PPD $name= " . Dumper(\@ppd) if $debug > 1;
	my ($printer);
	$printer = shift @ppd if $ppd[0] =~ /^Printer:/;
	print "$printer\n" if $printer;
	my $ppd = ppdfromvartoperl( \@ppd );
	if( not defined $ppd ){
		die "$progname: bad ppdfile $name\n";
	}
	print STDERR "PPD DB " . Dumper( $ppd ) if $debug;
	my $makemodel = ($ppd->{'makemodel'} or "");
	print "makemodel = $makemodel\n";
	my $args = $ppd->{'args'};
	print STDERR "PPD ARGS " . Dumper( $args ) if $debug;
	for my $argname ( @{$args} ) {
		my $name = $argname->{'name'};
		my $language = "postscript";
		if( $name =~ /^JCL(.*)$/ ){
			$argname->{'name'} = $1;
			$language = "pjl";
		}
		$argname->{'language'} = $language;
	}
	$key = 'name';
	for my $argname ( sort order_by_key @{$args} ) {
		my $name = $argname->{'name'};
		my $comment = ($argname->{'comment'} or "");
		my $type = ($argname->{'type'} or "");
		my $vals = ($argname->{'vals'} or []);
		my $default = ($argname->{'default'} or "");
		my $language = ($argname->{'language'} or "postscript");
		print STDERR "PPD ARG " . $name . "\n" if $debug;
		print STDERR "PPD VALUES " . Dumper( $vals ) . "\n" if $debug;
		my $values = "name=$name";
		$values .= "($comment)" if( $comment );
		$values .= ";";
		$values .= " language=$language;";
		$values .= " type=$type;" if( $type );
		$values .= " default=$default;" if( $default );
		$values .= " options=";
		if( not @{$vals} ){
			if( $type eq "bool" ){
				$values .= "True (True), False (False)";
			}
		} else {
			$key = 'value';
			for my $v ( sort order_by_key @{$vals} ){
				my $value = $v->{'value'};
				my $comment = ($v->{'comment'} or "");
				my $driverval = ($v->{'driverval'} or "");
				$driverval =~ s/[\s\n]+/ /gm;
				$driverval =~ s/^ //gm;
				$driverval =~ s/ $//gm;
				$driverval =~ s/[\W]/\\$&/gm;
				$driverval =~ s/\\ / /gm;
				$comment =~ s/[\W]/\\$&/g;
				$comment =~ s/\\ / /gm;
				$values .= "$value";
				$values .= " ($comment)" if( $comment );
				$values .= " [$driverval]" if( $driverval );
				$values .= ", ";
			}
			$values =~ s/, $/;/;
		}
		print $values . "\n";
	}
}
