(* main.sml
 *
 * COPYRIGHT (c) 1998 Bell Labs, Lucent Technologies.
 *
 * startup point for IS-GEN
 *)

structure ISGen =
struct

  open Util

  (* returns a list of components derived from the file names
   * in the win32/<version> directory, excluding license.txt
   * and setup.rul *)
  fun get_components (version) = let
    val d = OS.FileSys.openDir (version)
    fun acc "" = []
      | acc "license.txt" = acc (OS.FileSys.readDir (d))
      | acc "setup.rul" = acc (OS.FileSys.readDir (d))
      | acc f = f::(acc (OS.FileSys.readDir (d)))
    val l = acc (OS.FileSys.readDir (d))
  in
    OS.FileSys.closeDir (d);
    l
  end

  (* delete last character from a string, presumed to be newline *)
  fun stripNewline (i) = String.substring (i,0,size(i)-1)

  (* for each component description file in component list (comp_list),
   * return a triple of component name, IS Description string,
   * and IS Status Text *)
  fun get_descr (comp_list, version) = let
    fun f (x) = let
      val s = TextIO.openIn (concatP [version,x])
      val descr1 = stripNewline (TextIO.inputLine (s))
      val descr2 = stripNewline (TextIO.inputLine (s))
    in
      TextIO.closeIn (s);
      (x,descr1,descr2)
    end
  in
    map f comp_list
  end      


  fun file_groups (list,version,target,prefix) = let
    fun f (file) = (Verbose.message ["creating ",file, ".fgl"];
                    Fgl.make_fgl (concatP [version,file]
                                 ,concatP [target, "File Groups",
                                           file^".fgl"], prefix))
  in
    app f list
  end


  fun empty_txt (target) = let
    fun mk_empty (file) = let
      val s = TextIO.openOut (file)
    in
      Verbose.message ["creating ",file];
      TextIO.output (s,"\n");
      TextIO.closeOut (s)
    end
  in
    mk_empty (concatP [target,"Description.txt"]);
    mk_empty (concatP [target,"Instructions.txt"]);
    mk_empty (concatP [target,"Notes.txt"])
  end

  fun doit (version, target, prefix) = let
    val currDir = OS.FileSys.getDir ()
    val version' = OS.Path.file (version)
    val components_list = get_components (version)
    val comp_descr_list = get_descr (components_list,version)
  in
    Verbose.verbose := true;
    (* construct the target directory tree *)
    OS.FileSys.chDir (target);
    Verbose.message ["constructing target directory at ",target];
    DirTree.construct (DirTree.default_tree);
    OS.FileSys.chDir (currDir);
    (* copy the setup.rul file *)
    Verbose.message ["copying setup.rul"];
    copy (concatP [version,"setup.rul"],
          concatP [target,"Script Files","setup.rul"]);
    (* copy license file *)
    Verbose.message ["copying license.txt"];
    copy (concatP [version,"license.txt"],
          concatP [target,"Setup Files", "Compressed Files",
                   "Language Independent", "OS Independent", "license.txt"]);
    (* create empty .txt files *)
    empty_txt (target);
    (* dump all files which aren't component related *)
    Basic.dump (target,version');
    (* create components file + file groups file*)
    Components.make (comp_descr_list,concatP [target,"Component Definitions","Default.cdf"]);
    Components.make_fg (components_list,concatP [target,"File Groups","Default.fdf"]);
    (* create file groups *)
    file_groups(components_list,version,target,prefix)
    (* create .bat file *)
    (* BatchFile.create (target) -- not needed when using Media Wizard to
     *   compile and build *)
  end

end (* structure ISGen *)


structure Main : sig
                   val main :  string * string list -> OS.Process.status
		   val shell : string -> OS.Process.status
		 end =
struct

  fun report l = (app print ("ERROR -- "::l); print "\n")  

  fun reportException (e) = report [exnMessage e]

  fun check_path path = 
      if (OS.Path.isAbsolute (path)) then ()
      else (report ["path ",path," not absolute"];
	    raise Fail "")

  fun main (_,[version, target, prefix]) =
       ((app check_path [version,target,prefix];
	 ISGen.doit (version,target,prefix);
	 OS.Process.success)
        handle e => (reportException (e); OS.Process.failure))
    | main (_,l) = 
       (print ("Usage : IS-GEN <version> <target> <path-to-src>\n");
        OS.Process.failure)


(*
 * +----------------------------------------------------------------------
 * | What's the function Main.shell used for?
 * +----------------------------------------------------------------------
 * 
 * <grin> It's an idiosyncratic way for me to write my tools. It allows
 * one to call the tool from SML/NJ using command-line syntax (the one
 * you'd use from the shell, hence the name). For example, you'd CM.make()
 * is-gen and then do a 
 *  Main.shell "is-gen /foo/bar /baz/goo /bla/buf"
 * and so on. Just a convenience. - R
 *)

  fun shell cmdline =  let 
    val (hd::tl) = String.tokens (fn #" " => true | _ => false) cmdline
  in
    main (hd,tl)
  end

end (* structure Main *)
