#
# u2d.pl: Unix to DOS and reverse with no change in file name or time.
#         subroutines used by u2d.prl and d2u.prl.
#
# EF 95/11/14
#
# 95/11/14 - EF - modified to skip symbolic links
# 95/12/06 - EF - modified to read entire file into memory;
#                 no temporary file is used.
# 95/12/08 - EF - modified to use a temporary file if the
#                 source file exceeds a threshold size.
#                 The code is messy.
#
package d2u_u2d;


# package variables can be set to affect behavior.
# defaults:
#     $verbose   = 1  for a report of all major actions.
#     $skip_link = 1  to skip over (not convert) symbolic links
#     $max_to_memory = 500000;

$tmpfile = "ud_du.tmp";

sub main'd2u
{
   local(@filelist) = @_;
   $add_CR = 0;
   &convert;
}

sub main'u2d
{
   local(@filelist) = @_;
   $add_CR = 1;
   &convert;
}

sub convert
{
   $skip_link     = 1         unless defined($skip_link);
   $verbose       = 1         unless defined($verbose);
   $max_to_memory = 500000    unless defined($max_to_memory);
   print "\n";
   FILE:
   foreach $file (@filelist)
   {
      if (! -T $file)
      {
         $verbose && print "$file: not a text file or not found\n";
         next FILE;
      }
      if ( -l $file)
      {
         $linked_to = readlink($file);
         $verbose && print "$file: symbolic link to $linked_to";
         if ($skip_link)
         {
            print ", not converted\n";
            next FILE;
         }
         print "\n";
      }

      ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
            $atime, $mtime, $ctime, $blksize, $blocks) =
            stat($file);
      if ($size > $max_to_memory) {$use_tmp = 1;} else {$use_tmp = 0;}
      #
      eval <<'READ_OR_COPY';
      if ($use_tmp)
      {
         open(OUT, ">$tmpfile") || die "Can't open $tmpfile for copying $file\n";
         binmode(OUT);
      }
      open(IN, "<$file") || die "Can't open $file for reading.\n";
      binmode(IN);
      if ($use_tmp) { while (<IN>) { print(OUT) || die "writing $tmpfile"; } }
      else          { @lines = <IN>; }
      close(IN) || die;
      if ($use_tmp) { close(OUT) || die; }
READ_OR_COPY

      $@ && die "\nreading of $file failed with PERL message:\n $@";

      open(OUT, ">$file") || die "Can't open $file for writing.\n";
      binmode(OUT);
      $nCR = 0;
      $nLF = 0;
      if ($use_tmp) {
         open(IN, "<$tmpfile")
            || die "Can't open $tmpfile for conversion to $file\n";
         binmode(IN);
      }
      if ($use_tmp) { $get_lines = 'while ( <IN> )';     }
      else          { $get_lines = 'foreach ( @lines )'; }
      $trans = <<'TRANS';
      {
         $nCR += tr/\r//d;               # Clean out CRs if there, so they don't
                                         #  get duplicated.
         $nLF += s/\n/\r\n/ if $add_CR;  # Now replace LF with LF CR if DOS.
         print(OUT) || die "error writing $file\n";
      }
      close(OUT) || die "error closing $file\n";
TRANS
      eval "$get_lines\n$trans";
      #print "$get_lines\n$trans";
      if ($use_tmp)
      {
         close IN;
         ! $@ && unlink($tmpfile) || die "Can't unlink $tmpfile\n";
      }
      $@ && die "\nconversion of $file failed with PERL message:\n $@";

      utime ($atime, $mtime, $file) || warn "Can't set time of $file\n";
      $verbose && print "$file \t\t$size bytes\t$nCR CR del,\t$nLF LF->LFCR\n";
   }
}
1;
## (file loaded by "require" needs to return TRUE)
