/usr/bin/foomatic-ppd-to-xml is in foomatic-db-engine 4.0.12-2+b1.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320  | #!/usr/bin/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;
}
 |