Package: foomatic-filters
Version: 4.0.17-11
Severity: normal

the logic for PPD documentation extraction and presentation that was
present in foomatic 3.x was never migrated to the new codebase of versions 4.x.

however, the foomatic-rip manual page still states that you can get
a printout of the PPD options with "-o docs". this is misleading and incorrect
and should be removed.

the code in foomaticrip.c that is supposed to "Print documentation page
when asked for" (line 1460 or thereaboutes) doesn't and cannot, because
two lines down the track it just says 

/* Start the documentation page generator */
/* TODO tbd */

ie. there IS no documentation page generator - and the rest of the code then
builds up a really broken environment with a call out to a2ps & co (as per
bug 776315) and no input to those.

as upstream is clearly not inclined to do any work on stuff they left by the
wayside when the rewrote foomatic-rip multiple years ago, the '-o docs' option
should be rejected and not be allowed to cause this misleading mess.

however, if anybody does want that nice PPD option listing that the old
foomatic-rip gave us, here you are: i just recreated a cut down minimal version
of said PPD documentation extractor and presenter, which you find attached.
feel free to ship it in docs/contrib, it's under GPL 2.
#!/usr/bin/perl
#   $Id$
#
#   File:   ppd-doc-extractor
#   Date:   27 Jan 2022 16:28:17
#   Author:   Alexander Zangerl <a...@snafu.priv.at>
#
#   Abstract:
#    very minimal recreation of the PPD documentation extractor
#    of foomatic-rip 3.x (which you got with foomatic-rip -o docs), which
#    is not part of the rewritten 4.x versions despite the documentation's
#    claims and the broken option code that doesn't reject what it cannot
#    handle.
#
#   copyright (c) 2022 Alexander Zangerl <a...@snafu.priv.at>
#
#   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., 675 Mass Ave, Cambridge, MA 02139, USA.
use strict;
use File::Slurp;
use Data::Dumper;

my ($ppdfile,@a2ps) = @ARGV;
die "usage: $0 <ppdfile> [a2ps args]\n
no a2ps args: print to stdout
automatically added: --center-title, --footer\n\n" if (!-f $ppdfile);

my @stuff = read_file($ppdfile);

# parse everything but massage and handle just the relevant parts
my (%x, $curopengroup);
for (my $i = 0; $i <= $#stuff; ++$i)
{
  my $line = $stuff[$i];
  $line =~ s/\r\n$//;           # de-dos
  chomp $line;

  my ($key, $value, $option, $xlatoption);

  next if ($line =~ /^(\*%.*)?$/ or $line eq "*End");
  if ($line =~ /^\*([^:]+):\s*(.+)\s*$/)
  {
    ($key, $value) = ($1,$2);
    if ($key  =~ /^(\S+)\s+(.+)$/)
    {
      $key = $1;
      $option = $2;

      if ($option =~ m!^([^/]+)/(.+)$!)
      {
        ($option,$xlatoption) = ($1,$2);
        undef $xlatoption if ($xlatoption eq $option); # unnecessary ones
      }
    }
    # invocationvalue and quotedvalue allow continuation
    if ($value =~ /^"([^"]+)"\s*$/)
    {
      $value = $1;
    }
    elsif ($value =~ /^"([^"]*)*$/)
    {
      $value = $1;
      while ((my $nextline = $stuff[++$i]) !~ /"/)
      {
        $value .= $nextline;
      }
      if ($stuff[$i] =~ /^([^"]+)"\s*$/)
      {
        $value .= $1;
      }
    }

    # orderdependency is laid out extraspecially stupidly
    if ($key =~ /^(NonUI)?OrderDependency$/)
    {
      $key = "OrderDependency"; # we lump these together
      my ($num,$dontcare,$appliesto) = split(/\s+/,$value);
      ($option = $appliesto) =~ s/^\*//;
      $value = $num;
    }
    # want the options under openui w/o fluff
    elsif ($key eq "OpenUI")
    {
      $option =~ s/^\*//;
    }
    # another instance of shitty structural layout
    elsif ($key eq "OpenGroup")
    {
      if ($value =~ m!^\s*(\S+)/(.+)$!)
      {
        ($option,$xlatoption) = ($1,$2);
      }
      else
      {
        $xlatoption = $option = $value;
      }
      $curopengroup = $value = $option;
    }
    elsif ($key eq "CloseGroup")
    {
      undef $curopengroup;
    }

    if (defined $option)
    {
      # for option entries add a sequence number for sorting - simply use the 
line number
      $x{$key}->{$option} = { xlat => $xlatoption,
                              value => $value,
                              sequence => $i,
                              ingroup => $curopengroup, };

    }
    else
    {
      $x{$key} = $value;
    }
  }
  else
  {
    die "unrecognized line nr. $i\n";
  }
}

# print Dumper(\%x);

if (@a2ps)
{
  push @a2ps, ("--center-title=Documentation for $x{ModelName}","--footer=");

  # lazy me: just duping the pipe fd...
  open(P, "|-", "a2ps", @a2ps) or die "cannot pipe to a2ps: $!\n";
  open(STDOUT, ">&", \*P) or die "cannot dup: $!\n";
}

print qq|
Invocation summary for $x{ModelName}:
Command line: lpr [-Z opt=value, opt=value...] [lpr options] <file>

List of available options:\n\n|;

# meh...orderdependency is not in all ppds or all sections :-(
my $odep = $x{OrderDependency};
my @onames = sort { $odep->{$a}->{ingroup} cmp $odep->{$a}->{ingroup}
                    || $odep->{$a}->{sequence} <=> $odep->{$b}->{sequence}
                    || $odep->{$a}->{value} <=> $odep->{$b}->{value}
                    || $x{OpenUI}->{$a}->{sequence} <=> 
$x{OpenUI}->{$b}->{sequence} } keys %{$x{OpenUI}};

for my $oname (@onames)
{
  my $label = $x{OpenUI}->{$oname}->{xlat} // $oname;
  my $type = $x{OpenUI}->{$oname}->{value} // "Unknown";

  # one choice is no choice
  next if ($type eq "PickOne" && keys %{$x{$oname}} == 1);

  my $this = $x{$oname};
  my $example = (keys %$this)[0];
  my $sectionname = $x{OpenGroup}->{$this->{$example}->{ingroup}}->{xlat};
  my $sectionlabel = $sectionname ? "  Section: $sectionname\n":"";

  print "Option '$oname': $label\n$sectionlabel  Type: $type\n  Choices:\n";
  for my $choice (sort { $this->{$a}->{sequence} <=> $this->{$b}->{sequence} } 
keys %$this)
  {
    my $choicelabel = $x{$oname}->{$choice}->{xlat};
    print "   o '$choice'".($choicelabel? ": $choicelabel":"")."\n";
  }
  print "  Default: ".$x{"Default$oname"}."\n  Example: -Z $oname=$example\n\n";
}

if (@a2ps)
{
  close(STDOUT);
  close(P);
}

Reply via email to