#!/usr/local/bin/perl
#
# Usage:
#    ps2frag [-f] [-209] [-2e] [-x <pts>] [-y <pts>] files...
#
# ps2frag is part of the PSfrag system for integrating LaTeX typesetting
# and Encapsulated PostScript figures. Please refer to the PSfrag 
# documentation or the ps2frag man page for usage instructions.
#
# Please refer to the customization section below to set up this
# script to run on your platform. Sensible defaults for Unix systems
# have been supplied.
#
# Revision History:
#   12-Mar-95   Michael C. Grant  rearranged and updated for PSfrag2e.
#   26-Oct-93   Piet Tutelaers    ported to MSDOS and perlized
#   20-Sep-92   Craig Barratt     Released version 1.1.
#   17-Sep-92   Craig Barratt	  Made PS2FRAG settable by user.
#    9-Jun-92   Craig Barratt	  Changed egrep to grep for system V users.
#    1-Jun-92   Craig Barratt	  Released version 1.0.
#   28-Feb-92   Craig Barratt	  Initial version.
$| = -1;
print "This is ps2frag, version 2.0\n";

# --- BEGIN CUSTOMIZATION SECTION --- #

# Set $platform to your system type. Use ALL CAPITALS.
# Valid choices are: UNIX DOS
$platform = 'UNIX';

# You _may_ want to hard-code these values, but if $platform is
# set properly it will be unnecessary.
#   GS        the name of the GhostScript program.
#   PATHSEP   the character used to separate elements in your PATH.
#   tmpname   the name of a temporary file that PSfrag can read or
#             write to. In UNIX, '$$' is replaced by the process ID.
if ( $platform eq 'UNIX' ) {
    $GS = 'gs';
    $PATHSEP = ':';
    $tmpname = 'ps2frag.$$';
}   elsif ( $platform eq 'DOS' ) {
    $GS = 'gs386.exe';
    $PATHSEP = ';';
    $tmpname = 'ps2frag.tmp';
} else {
    die "Unknown platform: $platform (should be 'UNIX' or 'DOS')\n";
}

# The default location of the PS2FRAG file. The environment 
# variable PS2FRAG will override this value.
$PS2FRAG = '/usr/local/lib/texmf/dvips/ps2frag.ps';

# Choose the way you would LaTeX-2.09-style psfrag files to be
# named by uncommenting the appropriate line.
sub fragfile {
    local($_) = @_; 
#   example.eps --> example.epsfrag (will not work for DOS!)
    $_ .= 'frag';
#   example.eps --> example.frag (or example.fra for DOS)
#   s/(\.[^.]*)?$/.frag/;
    $_;
}

# If you want ps2frag to run in LaTeX-2.09 mode by default,
# change the value of $mode209 to '1'.
$mode209 = 0;
# This line looks at the name under which the program was run.
# If it is 'ps2psfrag', it assumes that LaTeX-2.09 compatibility
# is desired, since that was the old name used on UNIX. Comment
# this out if you don't want it.
$mode209 = 1 if $platform eq 'UNIX' && $0 =~ /ps2psfrag/;

# --- END CUSTOMIZATION SECTION--- #

$PS2FRAG = $ENV{'PS2FRAG'} if $ENV{'PS2FRAG'};
die "Can't open $PS2FRAG\n" unless -r $PS2FRAG;
foreach ( split(/$PATHSEP/,$ENV{'PATH'}) ) {
    $gsfile = "$_/$GS";
    last if -r $gsfile;
}
die "$GS: not found in $ENV{'PATH'}\n" unless $gsfile;
$ENV{'GS_LIB'} = $_ if $platform eq 'DOS';

$nfiles = 0;
$exitcode = 0;
$dx = $dy = $forced = 0;
print "LaTeX 2.09 compatibility mode enabled.\n" if $mode209;
sub usage { die "usage: $0 [-f] [-209] [-2e] [-x <pts>] [-y <pts>] files...\n"; }
&usage unless ( @ARGV );
FILELOOP:
while ($_ = shift) {
    if ( /^-f$/ ) { $forced = 1; next; }
    elsif ( /^-d[xy]$/ ) {
	$num = shift;
	die "invalid number: $_ $num\n" unless $num =~ /^-?\d*(\.\d*)?$/;
	$_ eq '-dx' ? ( $dx = $num ) : ( $dy = $num );
    } elsif ( /^-209$/ ) {
	print "LaTeX 2.09 compatibility mode enabled.\n" unless $mode209;
	$mode209 = 1;
    } elsif ( /^-2e$/ ) {
	print "LaTeX 2e mode enabled.\n" if $mode209;
	$mode209 = 0;
    } elsif ( /^-/ ) {
	print "Invalid option: $_\n";
	&usage;
    } else {
        $nfiles++;
	($fragin,$fragout,@header) = ($_,$tmpname);
	if ( !open(FRAGIN,"<$fragin") ) {
	    print "$fragin: could not open\n";
	    --$exitcode;
	    next FILELOOP;
	} else { print "$fragin: "; }
	$foundbb = 0;
	while (<FRAGIN>) {
	    if ( /^%%BoundingBox:/ ) { 
		$foundbb = 1; 
		push(@header,$_);
	    } elsif ( /^%PSfra/ ) {
		unless ( $forced || $mode209 ) {
		    print "already processed, skipping.\n";
		    close FRAGOUT; close FRAGIN; unlink $fragout;
		    next FILELOOP;
		}
	    } elsif ( /^%%EndComments/ || !/^%/ ) {
		$command = "$gsfile -dNODISPLAY -q -ddx=$dx -ddy=$dy " .
		    "-q $PS2FRAG -- $fragin";
		print "running gs...";
		open(GS, "$command|"); @ans = <GS>; close(GS);
		print "finished gs...";
		@errors = grep( !/^%/ && !/^\s+$/, @ans );
		if (@errors) {
		    print "errors found in:\n   $command\n",
		    $string = '   ' . '-' x (length($command)-2) . "\n";
		    print $string, grep(s/^/   /,@errors), $string;
		    close FRAGIN;
		    next FILELOOP;
		} elsif ( !open(FRAGOUT,">$fragout") ) {
		    die "could not open output file $fragout\n";
		} else {
		    @ans = grep( /^%/, @ans );
		    print FRAGOUT @header, "%PSfragBegin\n",
		        grep(/^%/,@ans), "%PSfragEnd\n", $_;
		    print FRAGOUT while <FRAGIN>;
		    close FRAGOUT; close FRAGIN;
		    rename ($fragout,$fragin);
		    if ( $mode209 ) {
			$fragout = &fragfile($fragin);
			if ( !open(FRAGOUT,">$fragout") ) {
                            print "could not open output file $fragout\n";
                            next FILELOOP;
			} 
			print FRAGOUT '%
% File automatically generated by the 209 compatibility mode
% of ps2frag and Ghostscript. It is included by \epsfbox or
% \psfragspecial. Do not \input directly or edit!
%
\begin{PSFragmentLocs}
';
			foreach (@ans) {
			    print FRAGOUT "  \\PsFragShowString$1\n"
				if /^%PSfragInfo({[^}]+})/;
			}
		        print FRAGOUT "  \\put(0,0){\\special{\\PsFragSpecialArgs}}\n";
              		foreach (@ans) {
			    if ( /^%PSfragInfo({[^}]*})\(([^,]*),([^)]*)\)\(([^,]*),([^)]*)\)\(([^,]*),([^)]*)\)({[^}]*})/ ) {
			        print FRAGOUT "  \\PsFragInfo$1\{$2\}\{$3\}\{$4\}\{$5\}\{$6\}\{$7\}$8\n";
			    } elsif ( /^%PSfragNext(.*)$/ ) {
				print FRAGOUT "  \\psfrag{}$1\n"; 
			    }
			}
                        print FRAGOUT "\\end{PSFragmentLocs}\n";
	                close FRAGOUT;
                    }
	            print "(no bounding box found!) " unless $foundbb;
                    print "processed.\n";
 		    next FILELOOP;
                }
	    } else { push(@header,$_); }
	}
    }
}
exit $exitcode;
