#!@PERL@
# -*- perl -*-
# Foomatic printer XML file generator to get XML files corresponding
# to manufacturer-supplied PostScript PPDs (or also PPDs from driver
# packages).
use Foomatic::Defaults;
use Foomatic::DB;
use Getopt::Std;
use Data::Dumper;
#use strict;
my $debug = 0;
# Program name
$0 =~ m!/([^/]+)\s*$!;
my $progname = ($1 || $0);
help() if !@ARGV;
#my ($opt_h, $opt_d, $opt_p, $opt_A, $opt_P, $opt_w);
getopts("d:r:p:lb:Dc:Cf:nxh");
help() if $opt_h;
my $drivers = $opt_d;
my $rdriver = $opt_r;
my $pdls = $opt_p;
my $ppdlink = $opt_l;
my $basedir = $opt_b;
my $addonlyrequesteddrivers = $opt_D;
my $comment = $opt_c;
my $nodefaultcomment = $opt_C;
my $destdir = $opt_f;
my $nomod = $opt_n;
my $nocheck = $opt_x;
my @ppddrivers = ();
my @driverslist = ($drivers ? split(',', $drivers) : ());
my $commentadded = 0;
foreach $ppdfile (@ARGV) {
my $ppddriver;
if ($ppdfile =~ /^([^\:]+)\:(.*)$/) {
$ppddriver = $1;
$ppdfile = $2;
} else {
$ppddriver = $driverslist[0];
}
$ppdlink = $opt_l;
if ($ppdlink && !$ppddriver) {
$ppdlink = 0;
warn("WARNING: \"-l\" set without assigning a driver to the PPD file \"$ppdfile\" and without supplying a driver via \"-d\". No links for this PPD file will get created!\n");
} elsif ($ppdlink && Foomatic::DB::member($ppddriver, @ppddrivers)) {
$ppdlink = 0;
warn("WARNING: \"-l\" set and PPD file \"$ppdfile\" assigned to the driver \"$ppddriver\", to which another PPD file was assigned already. No links for this PPD file will get created!\n");
}
if ($ppddriver && !Foomatic::DB::member($ppddriver, @ppddrivers)) {
push(@ppddrivers, $ppddriver);
}
if ($ppddriver && !Foomatic::DB::member($ppddriver, @driverslist)) {
push(@driverslist, $ppddriver);
}
print "PPD file $ppdfile";
if ($ppddriver) {
print " for driver $ppddriver\n";
} else {
print "\n";
}
my $ppddlpath;
if ($basedir) {
$basedir =~ s:/+$::;
if (! -d $basedir) {
die ("PPD base directory $basedir does not exist!\n");
}
if (! -r $ppdfile) {
$ppddlpath = $ppdfile;
$ppdfile = $basedir . "/" . $ppdfile;
if (! -r $ppdfile) {
die ("Given PPD file not found, neither as $ppddlpath nor as $ppdfile!\n");
}
} else {
$ppddlpath = $1 if $ppdfile =~ m:$basedir/(.*)$:;
}
} else {
if (! -r $ppdfile) {
die ("Given PPD file $ppdfile not found!\n");
}
$ppddlpath = $ppdfile;
}
my $parameters = {
(@driverslist ? ('drivers' => [@driverslist]) : ()),
($rdriver ? ('recommendeddriver' => $rdriver) : ()),
($pdls ? ('pdls' => [split(',', $pdls)]) : ()),
($ppddriver ? ('ppddriver' => $ppddriver) : ()),
($ppdlink ? ('ppdlink' => 1) : ()),
($basedir ? ('basedir' => $basedir) : ()),
($comment && !$commentadded ? ('comment' => $comment) : ()),
($nodefaultcomment && !$commentadded ? ('nodefaultcomment' => 1) : ()),
($addonlyrequesteddrivers ? ('addonlyrequesteddrivers' => 1) : ()),
};
$commentadded = 1;
my $db = Foomatic::DB->new();
my $dat = ppdtoperl($ppdfile, $parameters);
if ($ppddlpath eq "") {
$mk = $dat->{'id'};
$mk =~ s/^([^\-]+)\-.*$/$1/;
$ppd = $ppdfile;
$ppd =~ s:^.*/([^/]+):$1:;
$pdddlpath = "PPD/$mk/$ppd";
}
$ppddlpath =~ s/\.gz$//i;
$db->{'dat'} = $dat;
$db->{'dat'}{'comment'} =
" This database entry was automatically generated\n" .
" from the PPD file for this printer.<p>\n\n" .
$db->{'dat'}{'comment'} if !$parameters->{'nodefaultcomment'};
$db->{'dat'}{'functionality'} = "A";
foreach my $product (@{$db->{'dat'}{ppdproduct}}) {
$db->{'dat'}{'model'} =
Foomatic::DB::clean_manufacturer_name(Foomatic::DB::clean_model_name($product))
if scalar(@{$db->{'dat'}{ppdproduct}}) > 1;
$db->{'dat'}{'model'} =~ s/^$db->{'dat'}{'make'}\s*//i;
$db->{'dat'}{'id'} =
Foomatic::DB::generatepid($db->{'dat'}{'make'},
$db->{'dat'}{'model'});
if (scalar(@{$db->{'dat'}{ppdproduct}}) > 1) {
$db->{'dat'}{'general_mfg'} = $db->{'dat'}{'ppdmanufacturer'} if
$db->{'dat'}{'ppdmanufacturer'} &&
!$db->{'dat'}{'general_mfg'};
$db->{'dat'}{'general_mdl'} = $product;
$db->{'dat'}{'general_ieee'} = "MFG:" .
$db->{'dat'}{'general_mfg'} .
";MDL:" . $db->{'dat'}{'general_mdl'} . ";" .
($db->{'dat'}{'general_cmd'} ?
"CMD:" . $db->{'dat'}{'general_cmd'} . ";" : "");
}
$result = $db->perltoxml('p');
print " Creating new printer entry $db->{'dat'}{'id'}.xml ...\n";
my $f = ($destdir ? $destdir . "/" : ()) .
$db->{'dat'}{'id'} . ".xml";
open FILE, "> " . $f or
die "Cannot write file $db->{'dat'}{'id'}.xml!\n";
print FILE $result;
close FILE;
}
my @existing = ();
if (!$nocheck) {
@existing = $db->find_printer("$dat->{'make'}|$dat->{'model'}", 4, 1);
foreach my $product (@{$dat->{ppdproduct}}) {
my @pids = $db->find_printer("$dat->{'make'}|$product", 4, 1);
push(@existing,
grep {
!Foomatic::DB::member($_, @existing);
} @pids);
}
push(@existing,
grep {
!Foomatic::DB::member($_, @existing);
} map {
m:^(.*)\.xml$:; $1;
} map {
m:([^/]+)$:; $1;
} split(/\n/s,
`find $libdir/db/source/printer -name "*.xml" -print0 | xargs -0 grep -l $ppddlpath`));
}
delete($db->{'dat'});
foreach my $entry (@existing) {
my $d = $db->get_printer($entry);
my $result;
next if $d->{'noxmlentry'};
next if $nomod and $entry !~ /\.xml$/i;
$db->{'dat'} = $d;
if (!defined($parameters->{'drivers'})) {
$parameters->{'drivers'} = [$dat->{'driver'}];
}
if (!defined($parameters->{'pdls'})) {
$parameters->{'pdls'} = [split(',', $dat->{'general_cmd'})];
} else {
push(@{$parameters->{'pdls'}}, split(',', $dat->{'general_cmd'}));
}
Foomatic::DB::apply_driver_and_pdl_info($db->{'dat'}, $parameters);
$db->{'dat'}{'general_ieee'} = $dat->{'general_ieee'} if
defined($dat->{'general_ieee'}) &&
!defined($db->{'dat'}{'general_ieee'});
$db->{'dat'}{'general_mfg'} = $dat->{'general_mfg'} if
defined($dat->{'general_mfg'}) &&
!defined($db->{'dat'}{'general_mfg'});
$db->{'dat'}{'general_mdl'} = $dat->{'general_mdl'} if
defined($dat->{'general_mdl'}) &&
!defined($db->{'dat'}{'general_mdl'});
$db->{'dat'}{'general_des'} = $dat->{'general_des'} if
defined($dat->{'general_des'}) &&
!defined($db->{'dat'}{'general_des'});
$db->{'dat'}{'general_cmd'} = $dat->{'general_cmd'} if
defined($dat->{'general_cmd'}) &&
!defined($db->{'dat'}{'general_cmd'});
#$db->{'dat'}{'comment'} .= "\n <p>\n\n" . $dat->{'comment'};
my $xml1 = $db->perltoxml('p');
my $xml2 = $db->get_printer_xml($entry);
$xml2 =~ s/(<\/functionality>)/$1\n <driver><\/driver>/s if
$xml2 !~ /<driver>/;
$xml2 = transferregexp($xml1, $xml2,
'<driver>\S*<\/driver>');
$xml2 =~ s/(<\/driver>)/$1\n <drivers>\n <\/drivers>/s if
$xml2 !~ /<drivers>/;
$xml2 = transferregexp($xml1, $xml2,
'<drivers>.*<\/drivers>');
$xml2 =~ s/(<\/(mechanism|url)>)/$1\n <lang>\n <\/lang>/s if
$xml2 !~ /<lang>/;
$xml2 = transferregexp($xml1, $xml2,
'<lang>.*<\/lang>');
$xml2 =~ s/(<\/lang>)/$1\n <autodetect>\n <\/autodetect>/s if
$xml2 !~ /<autodetect>/;
$xml2 =~ s/(<autodetect>)/$1\n <general>\n <\/general>/s if
$xml2 !~ /<autodetect>[\s\n\r]*<general>/s;
$xml2 = transferregexp($xml1, $xml2,
'<autodetect>[\s\n\r]*<general>.*<\/general>');
$xml2 = transferregexp($xml1, $xml2,
'<\/drivers>[\s\n\r]*<comments>.*<\/comments>[\s\n\r]*<\/printer>');
$result = $xml2;
if ($entry !~ /\.xml$/i) {
print " Modifying printer entry $db->{'dat'}{'id'}.xml ...\n";
} else {
print " Adding PPD file to $db->{'dat'}{'id'}.xml ...\n";
}
open FILE, "> " . ($destdir ? $destdir . "/" : ()) .
$db->{'dat'}{'id'} . ".xml" or
die "Cannot write file $db->{'dat'}{'id'}.xml!\n";
print FILE $result;
close FILE;
delete($db->{'dat'});
}
undef($db);
undef($dat);
}
exit 0;
sub transferregexp {
my ($src, $dest, $regexp) = @_;
# This function copies the text fraction matching $regexp out of
# the first string, cuts the piece of the second matching $regexp
# out of the second string and replaces it by the piece copied
# from the first string. This is mainly for transfering XML
# sections from one XML file to another (strings can be
# multi-line) without needing to rewrite the unaffected parts of
# the XML file.
$src =~ m/($regexp)/s;
my $totransfer = $1;
$dest =~ s/$regexp/$totransfer/s if $totransfer;
return $dest;
}
sub help {
print <<HELP;
$progname <options> [<driver>:]<ppdfile> [[<driver>:]<ppdfile> ...]
$progname -h
<driver> : Driver to which the PPD file should get assigned. This
is optional. If not supplied, the first driver in the driver
list supplied via the "-d" option is used. Note that the PPD
files have to be supplied to different drivers, so with more
than one PPD drivers need to be specified here.
<ppdfile> : PPD file for which a printer XML file should be created
-d <drivers> : Comma-separated list of drivers with which the printer
works. First driver is the one for which the PPD file is.
If not otherwise stated by the "-r" option, this is also
the recommended driver. Drivers already specified together
with PPDs do no need to get specified with this option again.
The option is not needed if for all PPDs drivers are
specified.
-r <driver> : Recommended driver. Supply this option to specify another
driver than the driver from the PPD/the first one from the
"-d" argument as the recommended driver (or the one to which
the first PPD file is assigned if the "-d" option is not
used)..
-p <pdls> : Comma-separated list of known Page Description Languages
(PDLs) which the printer supports. This will add all
suitable drivers to the XML entry. Currently supported are:
Postscript, PCLXL, PCL6, PCL5e, PCL5c, PCL5, and PCL4.
-l : Add a link to the PPD file to the driver entry in the
XML file.
-b <directory> : Base directory for a relative link to the PPD. If the
base directory is given, the link set via the -l option
is relative to this directory (and not relative to the
current directory). With a base directory given the
<ppdfile> can also be given relative to this directory.
-D : Add only the driver requested by "-d" and "-r" to the
driver list in the XML file, do not add drivers based on
PDLs, not even on the PDLs supplied by the "-p" option.
-c <comment> : Add the given comment to the comment field of the XML
file. Comments are in HTML.
-C : Suppress any default comments (max paper width, pages
per minute, automatically generated XML, ...). Does not
suppress the comment supplied with "-c".
-f <directory> : Directory where the resulting XML file to write to. The
name of the file will be the printer ID with the ".xml"
extension.
-n : Do not write modified versions of existing XML files,
only create XML files for printers for which there is no
XML file yet.
-x : Create XML files independent of whether there are already
XML files for the printers covered by the PPD or not. This
makes the process vastly faster if you have PPD files for
printers which are for sure not yet in the Foomatic
database.
-h : show help information
HELP
exit 1;
}