This utility takes a dvips-generated postscript file, and creates a new potscript that has two of the pages of that on each new page. It only works for the output of dvips; for a4 paper only (because some magic numbers like 421.37259980 are hard-coded), and it can not put more than two pages on one page. It's ugly, but it works.
I tried to do this as a shell script first, but that attempt failed miserably.
#!/usr/bin/env perl
# creates a two-paged postscript file -- works for dvips-generated fil
+es only
# assumes a4 paper
use warnings;
use strict;
my $duper;
sub main {
@ARGV or
die "usage: psdup foo.ps";
for my $arg (@ARGV) {
$arg =~ /(.*)\.ps|(.*)/s or die "internal";
my $prefix = $+;
my $ifile = -e $arg ? $arg : -e $prefix . ".ps" ? $prefix . ".
+ps" :
die "cannot find file: $arg";
open my $I, "<", $ifile or
die "error opening file: $ifile";
my $tfile = $prefix . ".duptmp.ps";
my $ofile = $prefix . ".dup.ps";
open my $O, ">", $tfile or
die "cannot open temporary file $tfile";
my $s = 2;
$! = 0;
while (defined(my $l = <$I>)) {
$s and do {
2 == $s and
$l =~ /^%%Creator: dvips\b/ and
$s = 1;
1 == $s and
$l =~ /^%!$/ and
do {
print $O $duper or
die "error writing file $tfile: $!";
$s = 0;
};
};
print $O $l or
die "error writing file $tfile: $!";
}
$! and !$!{"EBADF"} and
die "error reading file $ifile: $!";
$s and
die "$ifile is not dvips-generated postscript";
close $O or
die "error closing file $tfile: $!";
system "ps2ps", $tfile, $ofile and
die "ps2ps failed";
unlink $tfile or
die "cannot unlink $tfile: $!";
}
}
$duper = <<'EOP';
%ambrus duper
/zbd { bind def } bind def
/z-showpage { showpage } zbd
/z-scale0 {
gsave 0 421.37259980 translate
0.70710678 0.70710678 scale -90.0 rotate
} zbd
/z-scale1 {
gsave 0 842.7451996 translate
0.70710678 0.70710678 scale -90.0 rotate
} zbd
/z-unscale { grestore } zbd
/z-dupe-odd false def
/z-flush { z-dupe-odd { z-showpage } if } zbd
/bop-hook {
z-dupe-odd { z-scale0 } { z-scale1 } ifelse
/z-dupe-odd z-dupe-odd not def
} zbd
/eop-hook { z-unscale z-dupe-odd not { showpage } if } zbd
/end-hook { /z-flush } zbd
/showpage { } zbd
%
EOP
main;
__END__