(*---------------------------------------------------------------------------
     Tools for detecting and eliminating the CR character from files.
 ---------------------------------------------------------------------------*)

app load ["BinIO", "FileSys", "Int"];
exception CANT_OPEN;

fun unCRfile file1 file2 = 
 let open BinIO
     val (istrm,ostrm) = (openIn file1, openOut file2)
     fun loop() =
       case input1 istrm
        of SOME ch => (if ch = 0wxD then () else output1(ostrm,ch) ; loop())
         | NONE    => (closeIn istrm; flushOut ostrm; closeOut ostrm)
  in loop()
  end;

fun variant str =  (* get an unused file name in the current directory *)
 if FileSys.access(str,[]) then 
 let fun vary i = let val s = str^Int.toString i
      in if FileSys.access(s,[]) then vary (i+1) else s 
      end
 in vary 0
 end
 else str;

fun unCR file = 
 let val file' = variant file
 in unCRfile file file'
  ; FileSys.remove file
  ; FileSys.rename{old=file', new=file}
 end  ;

fun ignoring file =
 case Path.ext file
  of SOME "exe" => true
   | SOME "ui"  => true
   | SOME "uo"  => true
   | SOME "so"  => true
   | other      => false;

fun hasCR file acc = 
 if ignoring file then (print ("ignoring "^file^"\n"); acc)
 else
 let open BinIO
     val istrm = openIn file handle _ => 
                 (print ("Unable to open "^file^"\n"); raise CANT_OPEN);
     fun loop() =
       case input1 istrm
        of SOME ch => if ch = 0wxD then (closeIn istrm; file::acc) else loop()
         | NONE    => (closeIn istrm ; acc)
  in loop()
  end

(*---------------------------------------------------------------------------
     fold a function over the files in a directory 
 ---------------------------------------------------------------------------*)

fun itDir f dir = 
  let val dstrm = FileSys.openDir dir
      fun loop acc =
        case FileSys.readDir dstrm
         of NONE => (FileSys.closeDir dstrm; acc)
          | SOME file => loop (f (dir,file) acc)
  in loop
  end

fun checkCR () = 
  itDir (fn (_,f) => fn l => (hasCR f l handle CANT_OPEN => l))
        (FileSys.getDir()) [];


(*---------------------------------------------------------------------------
   Typical usage: 

       run checkCR() in a directory, then map unCR over the result.
 ---------------------------------------------------------------------------*)
