#!/usr/local/bin/perl
# Accompanies LaTeX2HTML Version 0.6.4
# Rewrite of texexpand.  Handles style files and \endinput at least
# approximately right.
# Copyright Robert Thau, MIT AI lab, 1993.
# Unlimited reproduction is permitted as long as this notice is preserved.
# Mon Nov 22 1993
# Modified by Franz Vojik  to search
# for TeX-files in subdirectories of the given directories.
# Modified by Nikos Drakos  to look for 
#  as well as .tex when processing input and include commands.
# Tue Nov 23
# Modified by Nikos Drakos  to take an extra command line
# argument -save_styles  which instructs it to save in  the names
# of any style files or other included files.
# Tue Dec  7
# Modified by Nikos Drakos  to ignore comments!
# Also modified so that \input and \include do not have to be in the 
# beginning of a line. Text before or after such commands is preserved.
# Thu Dec 9 
# Modified by Nikos Drakos  to fix bug in the
# mechanism for ignoring comments!
# Wed Jan  5 1994
# Modified by Sebastian Rahtz 
# to recognise the documentclass and usepackage commands of LaTeX2e
# Also, modified by Nikos Drakos to print messages to STDERR.
# Jan 27 1994 - Nikos Drakos - Modified to strip spaces out of $styles
# Jan 28 1994 - Maximilian Ott  - added test that 
# checks for %'s before inluding|inputing files in include_line (otherwise
# input|include statements in .sty files cause infinite loops)
# Feb 14 1994 - Nikos Drakos - Fixed bug in code for checking for %'s 
# which caused \input and \include commands NOT to work!
# Also added support for \include'ing undelimited filenames.
# Mar 1 1994 - Sebastian Rahtz - Modified it to regard the main document style
# (eg book, report etc) as just another style that may have a corresponding
# perl translation module.
# June 11 1994 - Nikos Drakos - Special characters in names of style files
# used in regular expressions are now escaped (eg c++.sty) and now (20 June)
# are not escaped because this causes problems when reading other style files
# July 27 1994 - Nikos Drakos - Changed it so that the arguments of 
# documentclass and usepackage are processed correctly without being lost.
# Also modified do_include to return success or failure. If there is a failure
# then the corrsponding style file is added back in the options lists.
# Also changed it TO AUTOMATICALLY EXCLUDE any .sty and any .cls files
@texinputs = (".");
foreach $dir (split(/:/,$ENV{'TEXE_INPUTS'})) { push (@texinputs, $dir); }
foreach $dir (split(/:/,$ENV{'TEXINPUTS'})) { push (@texinputs, $dir); }
$homeDir = (getpwuid($<))[7];
grep(s|^~/|$homeDir/|, @texinputs);
grep((m|^~([^/]+)/|) && ($homeDir = (getpwnam($1))[7]) && (s||$homeDir/|), @texinputs);
@dont_include = split(/:/,$ENV{'TEXE_DONT_INCLUDE'});
while ($ARGV[0] =~ /^-/ && (! ($ARGV[0] =~ /^--$/)))
{
  $_ = shift;
  if (/^-dont_include$/) { push(@dont_include, shift); }
  elsif (/^-w$/) {}                     ### Compatibility hack.
  elsif (/^-auto_exclude$/) { $auto_exclude++}
  elsif (/^-save_styles$/) {$style_file = shift}
  elsif (/^-debug$/) { $debug++; }
  else { print STDERR "% --- WARNING:  Unrecognized option: $_ \n"; }
}
if ($debug)
{
  print STDERR "%TeX inputs are in:\n";
  foreach $dir (@texinputs) { print STDERR "%--- $dir\n"; }
  print STDERR "\n%Special names (not to be input or included):\n";
  foreach $name (@dont_include) { print STDERR "%--- $name\n"; }
  print STDERR "\n%Args:\n";
  foreach $arg (@ARGV) { print STDERR "%--- $arg\n"; }
  print "\n";
}
while (<>)
{
    $comments = '';
    s/(^%.*\n|([^\\])%.*\n)/do {$comments = $1;''}/eo; 
    if (/\\(input|include)\W/)
    { 
	print STDERR ("%Found include at top-level: $_") if $debug;
	&include_line ($_); 
    }
    elsif (/(\\document(style|class)\s*\[)(.*)(\]\s*\{)(.*)}/) {			        local ($before, $styles, $after) = ($`.$1, $3, $4.$5."}".$');			$styles =~ s/\s//go; # Strip spaces
	&should_include ($5 . ".sty");
	&include_styles($before, $styles, $after, ".sty");
										    }
# Package files are more complicated. we need to textually include them,
# to get the definitions, but how do we process the options?
# for now, we'll just lose the options. sorry 'bout that.
#
    elsif (/(\\usepackage.*\{)(.*)(\})/)
    {
	local ($before, $packages, $after) = ($`.$1, $2, $3.$');
	print STDERR "%Found package(s): --- $packages \n" if $debug;
	&include_styles($before, $packages, $after, ".sty");
    }
    else
    {
      print;
  }
    print "$comments";
}
sub include_styles 
{
    local ($before, $styles, $after, $ext) = @_;
    local ($style, @styles, @print_styles, @inc_styles);
    @styles = split(/,/, $styles);
    print STDERR "%Found styles: --- $styles \n" if $debug;
    foreach $style (@styles)
    {
      if (&should_include ($style . $ext)) { push (@inc_styles, $style); }
      else { push (@print_styles, $style); }
    }
    foreach $style (@inc_styles) {
	push (@print_styles, $style) unless &do_include ($style . $ext);
    }
    print $before . (join (',', @print_styles)) . $after;
}
    
sub include_line {
    local ($_) = @_;
    
    local ($filename, $found, $before, $after);
    
    if (/\\input\s*\{([^}]*)\}/) {($filename,$before,$after) = ($1, $`, $') }
    elsif (/\\input\s+(\S*)\s/) { ($filename,$before,$after) = ($1, $`, $') }
    elsif (/\\include\s*\{([^}]*)\}/) {($filename,$before,$after) = ($1, $`, $') }
    elsif (/\\include\s+(\S*)\s/) { ($filename,$before,$after) = ($1, $`, $') }
    else { print STDERR "texexpand --- COULDN'T FIND FILENAME in $_" };
    $filename =~ s/^\s*(\S*)\s*$/\1/;
    print $_ unless ((! ($before =~ /\s*[%]+\s*/)) &&
                    $filename && &should_include($filename) &&
                    &do_include ($filename, $before,$after))
    
}
# Returns success or failure
sub do_include
{
  local ($filename,$before,$after) = @_;
  local ($fname);
  
  
  if ($auto_exclude && ($filename =~ /\.(sty|cls)$/)) {
      print STDERR  "%--- ignoring $filename:  $_\n" if $debug;
      return(0);
  }
  
  print STDERR "%--- including $filename:  $_\n" if $debug;
  $found = 0;
  if ($filename =~ "^/")
  {
    $fname = $filename; $found = 1;
  }
  else
  {
    DIR:foreach $dir (@texinputs)
    {
	$fname = join ('/', $dir, $filename);
	print STDERR "%--- checking for $fname\n" if $debug;
	if (&file_or_ext)  { $found = 1; last DIR; }
	# Check Subdirs of texinputs
	else
	{ opendir(SUBDIR,$dir);         # open directory
	  while ($_=readdir(SUBDIR))    # read dir-entries
	  {  (/\./ || /\.\./) && (next);  # do not check . and ..
	     {  $dname = join ('/', $dir, $_);
		if (-d $dname )         # check subdirs
		{ $fname = join ('/', $dname, $filename);
		  print STDERR "%--- checking for $fname\n" if $debug;
		  if (&file_or_ext) { $found = 1; last DIR; }
	      }
	    }
	 }
      } 
    }
  }
  if (! $found)
  {
      print STDERR "texexpand --- COULDN'T FIND $filename!!!\n";
  }
  else
  {
    local (*incfile, $_);
    if (!open (incfile, $fname))
    {
      print STDERR "texexpand --- COULDN'T OPEN $fname --- $! !!!\n"
    }
    else
    {
	local($comments);
	print "$before";
	while ()
	{
	    $comments='';
 	    s/(^%.*\n|([^\\])%.*\n)/do {$comments = $1;''}/eo; 
	    last if /\\endinput/;
	    
	    if (/\\(input|include)\W/) { &include_line ($_); }
	    else { print }
	    print $comments;
	}
	print "$after";
	
	close (incfile);
    }				 
}
  $found;
}				 
sub should_include
{
  local ($_) = @_;
  # Recognize standard style options ...
  
  print STDERR "% --- Checking $_ for standard style\n" if $debug;
  #$_ = &escape_rx_chars($_);
  s/.*\///; s/\.(sty|cls|tex)//;          ### Get base name ...
  print STDERR "% --- Checking $_ for special style\n" if $debug;
  do {
      open (STYLES, ">>$style_file") ||
	  print STDERR "Cannot open $style_file $!\n";
      print STYLES "$_\n";
      close(STYLES)
      } if $style_file;
  
  if (/^(twoside|twocolumn|titlepage|openbib|leqno|fleqn|\d+pt)\.sty$/)
  { return 0; }
 
  local ($name) = $_;
  return ((!grep (/^$name$/, @dont_include))
	 );
}
sub file_or_ext {
    # Modifies $fname
    # if $fname exists return success otherwise
    # if $fname.tex exists, then bind $fname to $fname.tex and return success
    # else fail
    ((-f $fname) || ( (-f "$fname.tex") ? $fname = "$fname.tex" : 0));
}
# When part of the input text contains special perl characters and the text 
# is to be used as a pattern then these specials must be escaped.
sub escape_rx_chars {
    local($_) = @_;
    s/(\W)/\\$1/g;
    $_;
}