#!/usr/bin/perl
## latexmk - modified version 2.0


### John Verzani: Modified to accept switches for 
###               TeX, LaTeX, asmtex, and pdf for output. 
### see original file on a CTAN site


##
##   Modified by Evan McLean (emm@rdt.monash.edu.au)
##   Original script (RCS version 2.3) called "go" written by David J. Musliner
##
## - fully automated LaTeX document generation routine.
## - checks to see if .bib or .tex source files (or included other files)
##		have been changed since last run (which made .aux).
## - see sub print_help for info.
##
##  LatexMk is no longer supported by the author.  With changes in work
##  situation, the author no longer uses latex, and hence does not use
##  LatexMk.  Having no access to latex also makes it difficult to test fixes.
##
##-----------------------------------------------------------------------
## Here's the copyright notice that Mr. Musliner required to be
## kept here.
##-----------------------------------------------------------------------
##Copyright 1992 by David J. Musliner and The University of Michigan.
##
##                        All Rights Reserved
##
##Permission to use, copy, modify, and distribute this software and its
##documentation for any purpose and without fee is hereby granted,
##provided that the above copyright notice and this permission notice appear in
##all copies and modified versions.
##
##THE COPYRIGHT HOLDER(S) DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
##INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT 
##SHALL THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR 
##CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 
##DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 
##TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 
##PERFORMANCE OF THIS SOFTWARE.
##-----------------------------------------------------------------------
##While I am not copyrighting my modifications (I don't even know if I
##can) I do include my own disclaimer:
##
##THE AUTHOR/MODIFIER(S) DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
##INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT 
##SHALL THE AUTHOR/MODIFIER(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR 
##CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 
##DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 
##TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 
##PERFORMANCE OF THIS SOFTWARE.
##-----------------------------------------------------------------------

# ############### testing
# $temp='testdir/test.tex';
# ($ret,$message)=&latexmk($temp);
# print "returns: $ret, $message\n";

package latexmk;

sub latexmk {

  $version_num = 'modified 2.0';
  my  $debug=1;
  
  ## default document processing programs.
  $tex_flavor = "latex";		# default flavor
  
  @flavors = qw(tex amstex latex); # add in others??
  #################
  
  ### allows command line switches
  $tex = 'tex';
  $amstex='amstex';		
  $latex  = 'latex';		# for both latex and latex2e
  
  $tex_pdf = 'tex2pdf';		# whatever!!!!
  $amstex_pdf = 'amstex2pdf';
  $latex_pdf = 'latex2pdf';
  
  $bibtex  = 'bibtex';
  $slitex  = 'slitex';
  $makeindex  = 'makeindex';
  $dvips  = 'dvips';
  $dvips_landscape = 'dvips -tlandscape';
  $dviselect  = 'dviselect';
  $ps_previewer  = 'gv';
  $ps_previewer_landscape  = 'gv -swap';
  $dvi_previewer  = 'xdvi -s 4';
  $dvi_previewer_landscape = 'xdvi -s 4 -paper a4r';
  $dvi_cont_previewer  = 'xtex';
  $dvi_cont_previewer_landscape  = 'xtex';
  $lpr  = 'lpr';
  $tmpdir = '/tmp';
  $pscmd = 'ps -x';  # linux
  

  



  ## default flag settings.
  $pdf_mode = 0;			# pdf is 0 by default
  
  $bibtex_mode = 0;	# is there a bibliography needing bibtexing?
  $index_mode = 0;	# is there an index needing makeindex run?
  $landscape_mode = 0;	# default to portrait mode
  $sleep_time = 2;	# time to sleep b/w checks for file changes in -pvc mode
  $banner = 0;            # Non-zero if we have a banner to insert
  $banner_scale = 150;    # Original default scale
  $banner_intensity = 0.5;  # Darkness of the banner message
  $banner_message = 'Topology Atlas'; # Original default message
  $dvi_filter = '';	# DVI filter command
  $ps_filter = '';	# Postscript filter command
  
  ## Read rc files.
  # Read system rc file.
  $rcfile = '/usr/local/lib/Topology-Atlas/LatexMk';
  if ( -e $rcfile )
    {
      # Read the system rc file
      do "$rcfile";
    }
  
  # Read user rc file.
  $rcfile = "$ENV{'HOME'}/.latexmkrc";
  if ( -e $rcfile )
    {
      # Read the user rc file
      do "$rcfile";
    }
  
  # Read rc file in current directory.
  $rcfile = "latexmkrc";
  if ( -e $rcfile )
    {
      # Read the user rc file
      do "$rcfile";
    }
  
  
  ## Process command line args.
  ####### added some switches
  # -flavor for tex,latex,amstex,
  # -pdf ofr pdf output
  #######
  
  @the_file_list = ( );
  while ($_ = $_[0])		# was @ARGV
    {
      shift;
      if (/^-c$/)      { $cleanup_mode = 1; }
      elsif (/^-C$/)   { $cleanup_mode = 1; $cleanup_full_mode = 1; }
      elsif (/^-d$/)   { $banner = 1; }
      elsif (/^-f$/)   { $force_mode = 1; }
      elsif (/^-F$/)   { $force_include_mode = 1; }
      elsif (/^-g$/)   { $go_mode = 1; }
      elsif (/^-h$/)   { &print_help; }
      elsif (/^-i$/)   { $generate_and_save_includes = 1; }
      elsif (/^-I$/)   { $force_generate_and_save_includes = 1; }
      elsif (/^-l$/)   { $landscape_mode = 1; }
      elsif (/^-pvc$/) { $preview_continuous_mode = 1; }
      elsif (/^-pv$/)  { $preview_mode = 1; }
      elsif (/^-ps$/)  { $postscript_mode = 1; }
      elsif (/^-p$/)   { $printout_mode = 1; }
      elsif (/^-s$/)   { $slide_mode = 1; }
      elsif (/^-v$/)   { warn "\nLatexMk $version_num\n"; exit; }
      elsif (/^-r$/)   { if ( $_[0] eq '' ) {
	warn "LatexMk: No RC file specified\n"; &print_help; }
			 if ( -e $_[0] ) {
			   do "$_[0]"; } else {
			     &log_then_die("LatexMk: RC file [$_[0]] does not exist\n"); }
			 shift; }
      elsif (/^-bm$/)   { if ( $_[0] eq '' ) {
	warn "LatexMk: No message specified\n"; &print_help; }
			  $banner = 1; $banner_message = $_[0];
			  shift; }
      elsif (/^-bi$/)   { if ( $_[0] eq '' ) {
	warn "LatexMk: No intensity specified\n"; &print_help; }
			  $banner_intensity = $_[0];
			  shift; }
      elsif (/^-bs$/)   { if ( $_[0] eq '' ) {
	warn "LatexMk: No scale specified\n"; &print_help; }
			  $banner_scale = $_[0];
			  shift; }
      elsif (/^-dF$/)   { if ( $_[0] eq '' ) {
	warn "LatexMk: No dvi filter specified\n"; &print_help; }
			  $dvi_filter = $_[0];
			  shift; }
      elsif (/^-pF$/)   { if ( $_[0] eq '' ) {
	warn "LatexMk: No ps filter specified\n"; &print_help; }
			  $ps_filter = $_[0];
			  shift; }
      elsif (/^-flavor$/) {if ( $_[0] eq '' ) {
	warn "LatexMk: No flavor specified\n"; &print_help; }
			   $tex_flavor = $_[0];
			   shift; }
      elsif (/^-pdf$/) { $pdf_mode = 1;}
      elsif (/^-/)     { warn "LatexMk: $_ bad option\n"; }
      else             { @the_file_list = ( @the_file_list, $_ ); }
    }
  @_ = @the_file_list;
  
  
  
  ######### Make checks that flavors and output are valid choices
  foreach (@flavors) {
    $flavors{$_}=$_;
  }
  
  unless (defined $flavors{$tex_flavor}) {
    warn "latexmk: called with invalid flavor\n"; 
    &print_help;
  }
###  $tex_flavor = ${$tex_flavor};	# allows use of command line switches
  
  #### now check for pdf
  
  if ($pdf_mode) {
    $tex_flavor = $ {$tex_flavor."_".$pdf};
  }
  
  ############### 
  
  
  
  
  
  
  # Check we haven't selected mutually exclusive modes.
  # Note that -c overides all other options, but doesn't cause
  # an error if they are selected.
  if (($printout_mode && ( $preview_mode || $preview_continuous_mode ))
      || ( $preview_mode && $preview_continuous_mode ))
    {
      warn "LatexMk: Conflicting options (-p, -pv, -pvc) selected\n";
      &print_help;
    }
  
  
  # If seleced a previewer mode, make sure one and only one filename was specified
  if ($preview_mode || $preview_continuous_mode)
    {
      if (($_[0] eq '') || ($_[1] ne ''))
	{
	  warn"LatexMk: Need to specify one and only one filename for previewer mode\n";
	  &print_help;
	}
    }
  
  ##### must be called with a valid file name
  # If no files specified, try and find some
  # if ($_[0] eq '')
  # {
  #   @_=<*.tex $texfile_search>;
  # }
  
  # If still no files, exit.
  if ($_[0] eq '')
    {
      warn "LatexMk: No file name specified\n";
      &print_help; ## print_help function exits.
    }
  
  # If landscape mode, change modes
  if ( $landscape_mode )
    {
      $dvips = $dvips_landscape;
      $dvi_previewer = $dvi_previewer_landscape;
      $dvi_cont_previewer = $dvi_cont_previewer_landscape;
      $ps_previewer = $ps_previewer_landscape;
    }
  
  # Process for each file.
  foreach $filename ( @_ )
    {
      ## remove extention from filename if was given.

      ### JV -- if called with a directory, still on both

      if ( &find_basename($filename, $root_filename, $texfile_name) )
	{
	  &log_then_die ("LatexMk: Could not find file [$texfile_name]\n");
	}

      
      if ($cleanup_mode)
	{
	  ## Do clean if necessary
	  &cleanup;
	  if ($cleanup_full_mode)
	    {
	      &cleanup_full;
	    }
	}
      else
	{
	  ## Make file. ##
	  ## Find includes.
	  $includes = ''; 
	  $read_depend = 0;  # True to read depend file, false to generate it.
	  $depfile = "$root_filename.dep";
	  
	  ## Figure out if we read the dependency file or generate a new one.
	  if ( ! $force_generate_and_save_includes )
	    {
	      if ( $generate_and_save_includes )
		{
		  if ( -e $depfile )
		    {
		      # Compare timestamp of dependency file and root tex file.
		      $dep_mtime = &get_mtime("$depfile");
		      $tex_mtime = &get_mtime("$texfile_name");
		      if ( $tex_mtime < $dep_mtime )
			{
			  $read_depend = 1;
			}
		    }
		}
	      elsif ( -e $depfile )  # If dependency file already exists.
		{
		  $read_depend = 1;
		}
	    }
	  
	  if ( $read_depend )
	    {
	      # Read the dependency file
	      open(DEPFILE,$depfile) || log_then_die("LatexMk: Couldn't open dependency file [$root_filename.dep]\n");
	      while(<DEPFILE>) { eval; }
	      close(DEPFILE);
	    }
	  else
	    {
	      # Generate dependency file.
	      # get search paths for includes.
	      $psfigsearchpath = '.';
	      $TEXINPUTS = $ENV{'TEXINPUTS'} || "/usr/lib/texmf";
#	      if (!$TEXINPUTS) { $TEXINPUTS = "\.:$base_path"; }
	      $TEXINPUTS = "\.:$base_path:$TEXINPUTS";
	      ### add in the texinputs of base_path to environment
	      $ENV{"TEXINPUTS"} = $TEXINPUTS;
	      
	      $BIBINPUTS = $ENV{'BIBINPUTS'};
	  if (!$BIBINPUTS) { $BIBINPUTS = $TEXINPUTS; }
	### add in the bibinputs to environment  
	      $ENV{'BIBINPUTS'} = $BIBINPUTS;

	      &scan_for_includes("$texfile_name"); 
	      &update_depend_file;
	    }
	  
	  ## put root tex file into list of includes.
	  $includes .= " $texfile_name";
	  
	  ## before munging, save existing .aux file.
	  ## - if latex bombs, kill .aux, restore this backup to get back most
	  ## useful bib/ref info.
	  system("cp -p $root_filename.aux $root_filename.aux.bak > /dev/null 2>&1");
	  
	  #************************************************************
	  
	  &make_dependents("$includes");

	  ($ret,$ret_msg)=&make_latex_dvi;
	  if ($ret == 0) {
	    return (0,"latex_dvi failed: $ret_msg\n");
	  }
	  ($ret,$ret_msg)=&make_postscript;
	  if ($ret == 0) {
	    return (0,"make_postscript failed: $ret_msg\n");
	  }
	  ($ret,$ret_msg)=&make_printout;
	  if ($ret == 0) {
	    return (0,"make_printout failed: $ret_msg\n");
	  }
	  
	  ### all okay
	  return (1,"latexmk successful");
	  
# 	  if ($slide_mode) 
# 	    { 
# 	      &make_slitex_dvi; 
# 	    }
# 	  else
# 	    {
# 	      &make_latex_dvi;
# 	    }
#	  &make_dvi_filtered;
#	  &make_preview_continous;
#	  &make_preview;

	}
    }
}
#************************************************************
#### Subroutines
#************************************************************

sub make_latex_dvi
{
  $changed_dvi = 0 ;		# flag if anything changed.
  ## get initial last modified times.
  $tex_mtime = &get_latest_mtime($includes);
  $aux_mtime = &get_mtime("$root_filename.aux");
  $bbl_mtime = &get_mtime("$root_filename.bbl");
  $ilg_mtime = &get_mtime("$root_filename.ilg");
  $ind_mtime = &get_mtime("$root_filename.ind");


  ## - if no dvi file, or .aux older than tex file or bib file, run latex.
  if ( $go_mode || !(-e "$root_filename.dvi")
       || ($aux_mtime < $tex_mtime)
       || ($aux_mtime < $bbl_mtime)
       || ($aux_mtime < $ilg_mtime)
       || ($aux_mtime < $ind_mtime)
       || !(-e "$root_filename.aux")) {
    warn "------------\nRunning first $tex_flavor [$texfile_name]\n------------\n";
    &backup_toc;

########## change this line
####    $ret_val = system("$tex_flavor $texfile_name"); 

    $texfile_name =~ m!(.*)/(.*)!g;	# greedy, UNIX / not msdog

    $basedir = $1 || ".";
    $filename = $2 || $texfile_name;


    $ret_val = system("cd $basedir; echo \"\\nonstopmode \\input $filename\" | $tex_flavor");
    $changed_dvi = 1;

    if (!$force_mode && $ret_val)
    {
      $message="$tex_flavor encountered an error";
      &exit_msg($message,1);
      return(0,$message);
    }

    if  ($index_mode)
    {
      warn "------------\nRunning $makeindex [$root_filename]\n------------\n";
      $ret_val = system("$makeindex $root_filename");

      if (!$force_mode && $ret_val)
      {
	$message='Makeindex encountered an error';
        &exit_msg($message);
	return(0,$message);
      }
      $ilg_mtime = &get_mtime("$root_filename.ilg");
      $ind_mtime = &get_mtime("$root_filename.ind");
    }
  } else {
    return (1,"no need to run $tex_flavor");
  }

  $bib_mtime = &get_latest_mtime($bib_files);
  ## if no .bbl or .bib changed since last bibtex run, run bibtex.
  if ($bibtex_mode && (&check_for_bad_citation || !(-e "$root_filename.bbl")
     || ($bbl_mtime < $bib_mtime)))
  {
    warn "------------\nRunning $bibtex [$root_filename]\n------------\n";
    $ret_val = system("$bibtex $root_filename"); 
    $bbl_mtime = &get_mtime("$root_filename.bbl");
  }

  if ($bibtex_mode && &check_for_bibtex_errors)
  {
    if (!$force_mode)
    { 
      # touch a .bib file so that will rerun bibtex to fix errors.
      @split_bib_files = split(' ',$bib_files);
      system("touch $split_bib_files[0]");
      $message='Bibtex reported an error'; 
      &exit_msg($message); 
      return(0,$message);
    }
  }

  ## now, if need to, rerun latex up to twice to generate valid .dvi 
  ## w/ citations resolved.

  $dvi_mtime = &get_mtime("$root_filename.dvi");
  if ( ($dvi_mtime <= $bbl_mtime) || &check_for_reference_change 
     || ($dvi_mtime <= $ilg_mtime)
     || ($dvi_mtime <= $ind_mtime)
     || (&check_toc))
  {
    warn "------------\nRunning second $tex_flavor [$texfile_name]\n------------\n";
    &backup_toc;
####  Change this for nonstopmode
####    $ret_val = system("$latex $texfile_name"); 
    $ret_val = system("cd $basedir; echo \"\\nonstopmode \\input $filename\" | $tex_flavor");
    $changed_dvi = 1;
  }

  if (!$force_mode && $ret_val)
  {
    $message="$tex_flavor encountered an error";
    &exit_msg("$tex_flavor encountered an error",1);
    return(0,$message);
  }

  if (&check_for_reference_change || &check_toc)
  {
    warn "------------\nRunning third $tex_flavor [$texfile_name]\n------------\n";
    &backup_toc;
    $ret_val = system("cd $basedir; echo \"\\nonstopmode \\input $filename\" | $tex_flavor");
####### change again
#######    $ret_val = system("$latex $texfile_name"); 
    $changed_dvi = 1;
  }

  if (!$force_mode && &check_for_bad_reference)
  {
    $message='$tex_flavor could not resolve all references';
    &exit_msg('$tex_flavor could not resolve all references');
    return(0,$message);
  }

  if (!$force_mode && &check_for_bad_citation)
    {
      $message='$tex_flavor could not resolve all citations or labels';
      &exit_msg('$tex_flavor could not resolve all citations or labels');
      return(0,$message);
  }

  return (1,"$tex_flavor to dvi succesful");
}

#************************************************************

sub make_slitex_dvi
{
  $tex_mtime = &get_latest_mtime($includes);
  $dvi_mtime = &get_mtime("$root_filename.dvi");
  if ( $go_mode || !(-e "$root_filename.dvi") || ($dvi_mtime < $tex_mtime) )
  { 
    warn "------------\nRunning $slitex [$texfile_name]\n------------\n";
    $ret_val = system("$slitex $texfile_name"); 
  }
  if (!$force_mode && $ret_val)
  {
    $message='Slitex encountered an error';
    &exit_msg('Slitex encountered an error');
    return(0,$message);
  }
}

#************************************************************

sub make_dvi_filtered
{
  return if ( length($dvi_filter) == 0 );
  warn "------------\nRunning $dvi_filter [$root_filename]\n------------\n";
  system("$dvi_filter < $root_filename.dvi > $root_filename.dviF");
}

#************************************************************
# Finds the basename of the root file
# Arguments:
#  1 - Filename to breakdown
#  2 - Where to place base file
#  3 - Where to place tex file
#  Returns non-zero if tex file exists
sub find_basename
{
  my ($base_name,$ch,$ext,$base_path);

  $ch = '';
  $ext = '';
  $base_path = $_[0];
  while (( $ch ne '.' ) && ( $ch ne '/' ) && ( $base_path ne '' ))
  {
    $ext = $ch . $ext;
    $ch = chop $base_path;
  }
  if (( $ch eq '.' ) && ( $base_path ne '' ))
  {
    ## Found extention stuff
    $_[2] = $base_path . '.' . $ext;
    $_[1] = $base_path;		# keep basepath on root_filename -- JV
  }
  else
  {
    ## No extention
    $base_path = $_[0];
    $_[2] = $_[0];
    $_[1] = $base_path;		# keep basepath on root_filename -- JV
  }
#   $ch = '';
#   $base_name = '';
#   while (( $ch ne '/' ) && ( $base_path ne '' ))
#   {
#     $ch = chop $base_path;
#     if ( $ch ne '/' )
#     {
#       $base_name = $ch . $base_name;
#     }
#   }
#   ### root filename is just the file without directory. 
#   ### I want thisto be different. I want the directory
#   
#   $_[1] = $base_name;

  if ( ! -e $_[2] )
  {
    ## File does not exist, try adding a ".tex" extention
    if ( -e "$_[2].tex" )
    {
      # Adding the extention works, so put the extention back on the
      # basename
###      $_[1]  = $_[2];
      $_[2] .= '.tex';
      return(0);
    }
    return(1);
  }
  return(0);
}

#************************************************************

sub make_dependents
{
  my($file,$dep,$base_name,$ch,$toext,$fromext,$proptoext,$must,$func_name,$ret_val);

  foreach $file (split(' ',$_[0]))
  {
    $ch = '';
    $toext = '';
    $base_name = $file;
    while (( $ch ne '.' ) && ( $ch ne '/' ) && ( $base_name ne '' ))
    {
      $toext = $ch . $toext;
      $ch = chop $base_name;
    }
    if (( $ch eq '.' ) && ( $base_name ne '' ))
    {
      #Extracted proper extention.
      foreach $dep ( @cus_dep_list )
      {
	($fromext,$proptoext,$must,$func_name) = split(' ',$dep);
	if ( $toext eq $proptoext )
	{
	  # Found match
	  if ( -e "$base_name.$fromext" )
	  {
	    # From file exists, now check if it is newer
	    if (( ! (-e "$base_name.$toext" ))
		|| ( &get_mtime("$base_name.$toext")
		< &get_mtime("$base_name.$fromext") ))
	    {
	      warn "------------\nRunning $func_name [$base_name]\n------------\n";
	      $ret_val = &$func_name($base_name);
	      if ( !$force_mode && $ret_val )
	      {
		$message="$func_name encountered an error";
		&exit_msg("$func_name encountered an error");
		return(0,$message);
	      }
	    }
	  }
	  else
	  {
	    if ( !$force_mode && ( $must != 0 ))
	    {
	      $message="File '$base_name.$fromext' does not exist to build '$base_name.$toext'\n";
	      &exit_msg($message);
	      return(0,$message);
	    }
	  }
	}
      }
    }
  }
}

#************************************************************

sub make_printout
{
  return (1,"printout not needed") if (!$printout_mode);
  my ($ext);
  if ( length($ps_filter) == 0 )
  {
    $ext = '.ps';
  }
  else
  {
    $ext = '.psF';
  }
  warn "------------\nPrinting using $lpr [$root_filename]\n------------\n";
  $ret_val=system("$lpr $root_filename$ext");
  return (1,$ret_val);
}

#************************************************************

sub make_postscript
{
  if ( ! $banner )
  {
    return (1,"no postcript needed") if (!$postscript_mode && !$printout_mode);
  }
  my ($tmpfile,$header,$dvi_file);

  # Figure out the dvi file name
  if ( length($dvi_filter) == 0 )
  {
    $dvi_file = "$root_filename.dvi";
  }
  else
  {
    $dvi_file = "$root_filename.dviF";
  }

  # Do banner stuff
  if ( $banner )
  {
    ## Make temp banner file
    local (*INFILE,*OUTFILE,$count);

    $tmpfile = "$tmpdir/latexmk.$$";
    $count = 0;
    while ( -e $tmpfile )
    {
      $count = $count + 1;
      $tmpfile = "$tmpdir/latexmk.$$.$count";
    }
    if ( ! open(OUTFILE, ">$tmpfile") ) {
      &log_then_die ("LatexMk: Could not open temporary file [$tmpfile]\n"); }
    print OUTFILE "userdict begin /bop-hook{gsave 200 30 translate\n";
    print OUTFILE "65 rotate /Times-Roman findfont $banner_scale scalefont setfont\n";
    print OUTFILE "0 0 moveto $banner_intensity setgray ($banner_message) show grestore}def end\n";
    close(OUTFILE);
    $header = "-h $tmpfile";
  }
  else
  {
    $header = '';
  }

  $ps_mtime = &get_mtime("$root_filename.ps");
  $dvi_mtime = &get_mtime("$dvi_file");
  if (( $ps_mtime < $dvi_mtime ) || $banner )
  {
    warn "------------\nRunning $dvips [$root_filename]\n------------\n";
    system("$dvips $header $dvi_file -o $root_filename.ps");
  }

  if ( $banner )
  {
    unlink("$tmpfile");
  }

  ## Do we have postscript filtering?
  if ( length($ps_filter) != 0 )
  {
    warn "------------\nRunning $ps_filter [$root_filename]\n------------\n";
    system("$ps_filter < $root_filename.ps > $root_filename.psF");
  }
  return (1,"postcript sucessful");
}

#************************************************************
# run appropriate previewer.

sub make_preview
{
  return if (!$preview_mode);
  $viewer = $dvi_previewer;
  $ext = '.dvi';
  if ($postscript_mode)
  {
    $viewer = $ps_previewer;
    $ext = '.ps';
    if ( length($ps_filter) != 0 )
    {
      $ext = '.psF';
    }
  }
  else
  {
    if ( length($dvi_filter) != 0 )
    {
      $ext = '.dviF';
    }
  }
  warn "------------\nStarting previewer: $viewer $root_filename$ext\n------------\n";
  exec("$viewer $root_filename$ext")||  
    warn "LatexMk: Could not start previewer [$viewer $root_filename$ext]";
  exit;
}

sub backup_toc
{
  if ( -e "$root_filename.toc" )
  {
    system(
      "cp -p $root_filename.toc $root_filename.toc.bak > /dev/null 2>&1");
  }
}

#************************************************************
# Compare the toc file with the backup.  If they differ then
# return non-zero.
sub check_toc
{
  my($ret_val);

  if ( -e "$root_filename.toc" )
  {
    if ( -e "$root_filename.toc.bak" )
    {
      $ret_val = system(
	"diff $root_filename.toc.bak $root_filename.toc > /dev/null 2>&1");
    }
    else
    {
      $ret_val = 1;
    }
  }
  else
  {
    $ret_val = 0;
  }
  return($ret_val);
}

#************************************************************
# arg1 = name

sub find_process_id
{
  my(@command, $lookingfor);
  @ps_output = `$pscmd`;
  shift(@ps_output);  # Discard the header line from ps
  foreach (@ps_output)
  {
#    s/\s+/ /g;  #Compress multiple spaces.
    ($pid,$tt,$stat,$time,@command) = split(' ',$_);
    if ("@command" eq "$_[0]")
    {
      return($pid);
    }
  }
  return(0);
}

#************************************************************

sub make_preview_continous
{
  return if (!$preview_continuous_mode);
  #
  my ($dvi_file);
  # get the value of SIGUSR1, defaults to SPARC value.
  if (!(do 'signal.ph'))
  {
    eval 'sub SIGUSR1 {30;}';
  }
  # Figure out the dvi file name
  if ( length($dvi_filter) == 0 )
  {
    $dvi_file = "$root_filename.dvi";
  }
  else
  {
    $dvi_file = "$root_filename.dviF";
  }
  # note, we only launch a previewer if one isnt already running...
  # otherwise we'll send reopen signals to the existing previewer.
  if ($previewer_pid = &find_process_id("$dvi_cont_previewer $dvi_file"))
  {
    warn "------------\nReattached to existing previewer, pid=$pid\n------------\n";
    kill &SIGUSR1,$previewer_pid;
  }
  else
  {
    if (!($previewer_pid = fork))
    {
      # in forked child, close off from parent so previewer runs on
      # after parent 'latexmk' dies.
      setpgrp($$,0);
      warn "------------\n$dvi_cont_previewer $dvi_file\n------------\n";
      exec("$dvi_cont_previewer $dvi_file")||
	warn "LatexMk: Failed to exec file viewer\n";
      exit;
    }
  }
  # Loop forever, rebuilding .dvi as necessary.
  while ( 1 )
  {
    sleep($sleep_time);
    if ($slide_mode) 
    { 
      &make_slitex_dvi; 
    }
    else
    {
      &make_latex_dvi;
    }
    if ($changed_dvi)
    {
      kill &SIGUSR1,$previewer_pid;
    }
  }
}

#************************************************************

sub get_mtime
{
  my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,
			$ctime,$blksize,$blocks) = stat($_[0]);
  $mtime;
}

#************************************************************

sub check_for_reference_change
{
  my $logfile = "$root_filename.log";
  open(LOGFILE,$logfile) || &log_then_die("LatexMk: Could not open log file to check for reference check\n");
  while(<LOGFILE>)
  { 
    if (/Rerun to get/) { return 1; } 
  }
  0;
}

#************************************************************

sub check_for_bad_reference
{
  my $logfile = "$root_filename.log";
  open(LOGFILE,$logfile) || log_then_die("LatexMk: Could not open log file to check for bad reference\n");
  while (<LOGFILE>)
  {
    if (/LaTeX Warning: Reference[^\001]*undefined./) { return 1; } 
  }
  0;
}

#************************************************************
# check for citation which latex couldnt resolve.

sub check_for_bad_citation
{
  my $logfile = "$root_filename.log";
  open(LOGFILE,$logfile) || log_then_die("LatexMk: Could not open log file to check for bad citation\n");
  while (<LOGFILE>)
  {
    if (/LaTeX Warning: Citation[^\001]*undefined./) { return 1; }
  }
  0;
}

#************************************************************
# check for citation which bibtex didnt find.

sub check_for_bibtex_errors
{
  my $logfile = "$root_filename.blg";
  open(LOGFILE,$logfile) || log_then_die("LatexMk: Could not open bibtex log file error check\n");
  while (<LOGFILE>)
  {
    if (/Warning--/) { return 1; }
    if (/error message/) { return 1; }
  }
  0;
}

#************************************************************
# cleanup
# - erases all generated files, exits w/ no other processing.

sub cleanup
{
  unlink("$root_filename.aux");
  unlink("$root_filename.aux.bak");
  unlink("$root_filename.bbl");
  unlink("$root_filename.blg");
  unlink("$root_filename.log");
  unlink("$root_filename.ind");
  unlink("$root_filename.idx");
  unlink("$root_filename.ilg");
  unlink("$root_filename.toc");
  unlink("$root_filename.toc.bak");
  unlink("$root_filename.lof");
  unlink("$root_filename.lot");
  unlink("$root_filename.dep");
  unlink("texput.log");
  unlink("texput.aux");

  # .aux files are also made for \include'd files
  foreach $include (split(' ',$includes))
  { 
    $include =~ s/\.[^\.]*$/.aux/;
    unlink($include);
  }
  # Do any other file extentions specified
  foreach $ext (split(' ',$clean_ext))
  {
    unlink("$root_filename.$ext");
  }
}

#************************************************************
sub cleanup_full
{
  unlink("$root_filename.dvi");
  unlink("$root_filename.ps");
  unlink("$root_filename.dviF");
  unlink("$root_filename.psF");
  unlink("texput.dvi");
  # Do any other file extentions specified
  foreach $ext (split(' ',$clean_full_ext))
  {
    unlink("$root_filename.$ext");
  }
}

#************************************************************
sub print_help
{
  warn "LatexMk $version_num: Automatic LaTeX document generation routine\n\n";
  warn "Usage: latexmk [latexmk_options] [filename ...]\n\n";
  warn "  LatexMk_options:\n";
  warn "   -bm <message> - Print message across the page when converting to postscript\n";
  warn "   -bi <intensity> - Set contrast or intensity of banner\n";
  warn "   -bs <scale> - Set scale for banner\n";
  warn "   -c 	- clean up (remove) all nonessential files\n";
  warn "   -C 	- clean up (remove) all nonessential files\n";
  warn "          including dvi and postscript files\n";
  warn "   -d   - Print `DRAFT' across the page when converting to postscript\n";
  warn "   -dF <filter> - Filter to apply to dvi file\n";
  warn "   -f 	- force continued processing past errors\n";
  warn "   -F 	- Ignore non-existent files when making dependencies\n";
  warn "   -g 	- process regardless of file timestamps\n";
  warn "   -h 	- print help\n";
  warn "   -i 	- rescan for includes if depenancy file older than tex file\n";
  warn "   -I 	- force rescan for includes\n";
  warn "   -l   - force landscape mode\n";
  warn "   -ps 	- generate postscript\n";
  warn "   -pF <filter> - Filter to apply to postscript file\n";
  warn "   -p   - print document after generating postscript\n";
  warn "   -pv  - preview document\n";
  warn "   -pvc - preview document and continuously update\n";
  warn "   -r <file> - Read custom RC file\n";
  warn "   -s   - set slide mode\n";
  warn "   -v   - display program version\n";
  warn "   filename = the root filename of LaTeX document\n";
  warn "\n  -p, -pv and -pvc are mutually exclusive\n";
  warn "  -h, -c and -C overides all other options.\n";
  warn "  -pv and -pvc require one and only one filename specified\n";
  warn "  Contents of RC file specified by -r overrides options specified\n";
  warn "    before the -r option on the command line\n";

  exit;
}

#************************************************************
# - stats all files listed in first arg, returns most recent modify time of all.

sub get_latest_mtime
{
  my($ret_val_mtime) = 0;
  foreach $include (split(' ',$_[0]))
  {
    $include_mtime = &get_mtime($include);
    if ($include_mtime >  $ret_val_mtime)
    {
      $ret_val_mtime = $include_mtime;
    }
  }
  $ret_val_mtime;
}

#************************************************************
# - looks recursively for included & inputted and psfig'd files and puts
#   them into $includes.
# - note only primitive comment removal: cannot deal with escaped %s, but then,
#	when would they occur in any line important to LatexMk??

sub scan_for_includes
{
  warn "------------\nGenerating Dependency File [$root_filename]\n------------\n";
  &scan_for_includes_($_[0]);
}

sub scan_for_includes_
{
  local *FILE;
  my ($orig_filename,$full_filename1,$full_filename2);
  if (!open(FILE,$_[0])) 
  {
    warn "LatexMk: could not open input file [$_[0]]\n";
    return;
  }
  while(<FILE>)
  {
    ($_,$junk) = split('%',$_);		# primitive comment removal.
    if (/\\include[{\s]+([^\001\040\011}]*)[\s}]/)
    {
      $full_filename = $1;
      $orig_filename = $full_filename;
      $full_filename1 = &find_file($full_filename,$TEXINPUTS,'1');

      if (( $full_filename1 eq '' ) || ( ! -e $full_filename1 ))
      {
        $full_filename2 = &find_file("$full_filename.tex",$TEXINPUTS,'1');
        if (( $full_filename2 ne '' ) && ( -e $full_filename2 ))
        {
          $full_filename = $full_filename2;
        }
        else
        {
          $full_filename = $full_filename1;
        }
      }
      else
      {
        $full_filename = $full_filename1;
      }

      if ($full_filename)
      {
      	$includes .= "$full_filename ";
	if ( -e $full_filename )
	{
	  warn "	Found include for file [$full_filename]\n";
	  &scan_for_includes_($full_filename);
	}
        else
        {
          if ( $orig_filename =~ /^\// )
          {
            warn "LatexMk: Could not find file [$orig_filename]\n";
          }
          else
          {
            warn "LatexMk: Could not find file [$orig_filename] in path [$TEXINPUTS]\n";
            warn "         assuming in current directory ($full_filename)\n";
          }
        }
      }
      else
      {
        if ( ! $force_include_mode )
        {
          if ( $orig_filename =~ /^\// )
          {
            &log_then_die ("LatexMk: Could not find file [$orig_filename]\n");
          }
          else
          {
            &log_then_die ("LatexMk: Could not find file [$orig_filename] in path [$TEXINPUTS]\n");
          }
        }
      }
    }
    elsif (/\\input[{\s]+([^\001\040\011}]*)[\s}]/)
    {
      $full_filename = $1;
      $orig_filename = $full_filename;
      $full_filename1 = &find_file($full_filename,$TEXINPUTS,'1');

      if (( $full_filename1 eq '' ) || ( ! -e $full_filename1 ))
      {
	$full_filename2 = &find_file("$full_filename.tex",$TEXINPUTS,'1');
	if (( $full_filename2 ne '' ) && ( -e $full_filename2 ))
	{
	  $full_filename = $full_filename2;
	}
	else
	{
	  $full_filename = $full_filename1;
	}
      }
      else
      {
	$full_filename = $full_filename1;
      }

      if ($full_filename)
      {
	$includes .= "$full_filename ";
	warn "added '$full_filename'\n";
	if ( -e $full_filename )
	{
	  warn "	Found input for file [$full_filename]\n";
	  &scan_for_includes_($full_filename);
	}
	else
	{
	  if ( $orig_filename =~ /^\// )
	  {
	    warn "LatexMk: Could not find file [$orig_filename]\n";
	  }
	  else
	  {
	    warn "LatexMk: Could not find file [$orig_filename] in path [$TEXINPUTS]\n";
	    warn "         assuming in current directory ($full_filename)\n";
	  }
	}
      }
      else
      {
	if ( ! $force_include_mode )
	{
	  if ( $orig_filename =~ /^\// )
	  {
	    &log_then_die ("LatexMk: Could not find file [$orig_filename]\n");
	  }
	  else
	  {
	    &log_then_die ("LatexMk: Could not find file [$orig_filename] in path [$TEXINPUTS]\n");
	  }
	}
      }
    }
    elsif (/\\blackandwhite{([^\001\040\011}]*)}/ || /\\colorslides{([^\001}]*)}/)
    {
      $slide_mode = 1;
      $full_filename = $1;
      if ($1 =~ m/\./)
      {
        $full_filename = &find_file($full_filename,$TEXINPUTS);
      }
      else
      {
        $full_filename = &find_file("$full_filename.tex",$TEXINPUTS);
      }
      if ($full_filename)
      {
      	$includes .= "$full_filename ";
	if ( -e $full_filename )
	{
	  warn "	Found slide input for file [$full_filename]\n";
	  &scan_for_includes_($full_filename);
	}
      }
    }
    elsif (/\\psfig{file=([^,}]+)/ || /\\psfig{figure=([^,}]+)/)
    {
      $full_filename = &find_file($1,$psfigsearchpath);
      if ($full_filename)
      {
      	$includes .= "$full_filename ";
	if ( -e $full_filename )
	{
	  warn "	Found psfig for file [$full_filename]\n";
	}
      }
    }
    elsif ( /\\epsfbox{([^}]+)}/ || /\\epsfbox\[[^\]]*\]{([^}]+)}/ ||
	    /\\epsffile{([^}]+)}/ || /\\epsffile\[[^\]]*\]{([^}]+)}/ ||
	    /\\epsfig{file=([^,}]+)/ || /\\epsfig{figure=([^,}]+)/ )
    {
      $full_filename = &find_file($1,$TEXINPUTS);
      if ($full_filename)
      {
      	$includes .= "$full_filename ";
	if ( -e $full_filename )
	{
	  warn "	Found epsf for file [$full_filename]\n";
	}
      }
    }
    elsif (/\\documentstyle[^\000]+landscape/)
    {
      warn "	Detected landscape mode\n";
      $landscape_mode = 1;
    }
    elsif (/\\bibliography{([^}]+)}/)
    {
      $bib_files = $1;
      $bib_files =~ tr/,/ /;
      $bib_files = &find_file_list($bib_files,'.bib',$BIBINPUTS);
      warn "	Found bibliography files [$bib_files]\n";
      $bibtex_mode = 1;
    }
    elsif (/\\psfigsearchpath{([^}]+)}/)
    {
      $psfigsearchpath = $1;
    }
    elsif (/\\makeindex/)
    {
      $index_mode = 1;
      warn "        Detected index mode\n";
    }
  }
}

#************************************************************
# given filename and path, return full name of file, or die if none found.
# when force_include_mode=1, only warn if an include file was not
# found, and return 0 (PvdS).

sub find_file
{
  if ( $_[0] =~ /^\// )
  {
    if ($force_include_mode)
    {
	if ( $_[2] eq '' )
	{
	  warn "LatexMk: Could not find file [$_[0]]\n";
	}
	return("$_[0]");
    }
    else
    {
	if (-e $_[0])
	{
	  return("$_[0]");
	}
	&log_then_die ("LatexMk: Could not find file [$_[0]]\n");
    }
  }
  foreach $dir (split(':',$_[1]))
  {
    if (-e "$dir/$_[0]")
    {
      return("$dir/$_[0]");
    }
  }
  if ($force_include_mode)
  {
	if ( $_[2] eq '' )
	{
	  warn "LatexMk: Could not find file [$_[0]] in path [$_[1]]\n";
	  warn "         assuming in current directory (./$_[0])\n";
	}
	return("./$_[0]");
  }
  else
  {
	if ( $_[2] ne '' )
	{
	  return('');
	}
  	&log_then_die ("LatexMk: Could not find file [$_[0]] in path [$_[1]]\n");
  }
}

#************************************************************
# given space sep list of filenames, a file suffix, and a path, return list of 
# full names of files, or die w/ warning if not found.
# When $force_include_mode=1, don't die and don't append the file names (PvdS).

sub find_file_list
{
  my($tmp_file,$return_list) = '';
  foreach $file (split(' ',$_[0]))
  {
    $tmp_file = &find_file("$file$_[1]",$_[2]);
    if ($tmp_file)
    {
    	$return_list .= $tmp_file . " ";
    }
  }
  $return_list;
}

#************************************************************
sub exit_msg
{
   warn "\n------------\n";
   warn "LatexMk: $_[0].\n";
   warn "-- Use the -f option to force complete processing.\n";
   if ($_[1])
   {
     warn "LatexMk: restoring last $root_filename.aux file\n";
     system("cp -p $root_filename.aux.bak $root_filename.aux > /dev/null 2>&1");
   }
#   exit;
}

#************************************************************

sub update_depend_file
{
  warn "Writing dependency file [$root_filename.dep]\n";
  $rcfile = ">$root_filename.dep";
  open(RCFILE,$rcfile) || &log_then_die ("LatexMk: Unable to open dependency file [$rcfile] for updating\n");
  print RCFILE '$includes = \'' . "$includes';\n";
  print RCFILE '$bib_files = \'' . "$bib_files';\n";
  if ($slide_mode)
  {
    print RCFILE '$slide_mode = 1;' . "\n";
  }
  if ($bibtex_mode)
  {
    print RCFILE '$bibtex_mode = 1;' . "\n";
  }
  if ($index_mode)
  {
    print RCFILE '$index_mode = 1;' . "\n";
  }
  close RCFILE;
}


sub log_then_die {
  ##### this needs work -- tie in with exi_msg and logging
  &exit_msg(@_);
}


1; ### in case this gets required
