(**********************************************************************)
(* (c) Greg Morrisett, Neal Glew                                      *)
(*     June 1998, all rights reserved.                                *)
(**********************************************************************)

(* Modified by Dan to remove statistics *)

open Utilities;;
open Talbe;;
open Gcd;;

let linkc = ref false;;
let progc = ref false;;
let print_linked_interface = ref false;;

let imexs = ref [];;
let imports = ref ["tal.tali"];;

let add_std_lib s =
  add_object_file (s^Talout.object_file_suffix);
  imports := (s^".tali") :: !imports
;;

let compile_tal_file filename basename modname =
  try
    let talm = read_imp filename in
    let imex = verify filename talm in
    if assemble_p () then begin
      let objfile = basename ^ Talout.object_file_suffix in 
      if not (asm filename talm imex objfile) then raise Gcdfec.Exit; 
      add_object_file objfile
    end;
    imexs := imex :: !imexs;
    true
  with Gcdfec.Exit | Talctxt.Talfail -> false
;;

let middle () = true;;

let do_link objectfiles libraries executable =
  try
    if !linkc then begin
      try
      	let imex = Tallinkchk.verify_link (List.rev !imexs) in
      	Printf.printf "LINK Verified\n"; flush stdout;
      	if !print_linked_interface then begin
	  let (it,et) = imex in
	  print_string "TAL Linked Interface"; print_newline ();
	  print_string "Imports"; print_newline ();
	  Talpp.print_tal_int_type Format.std_formatter Talpp.std_options it;
	  Format.print_newline ();
	  print_string "Exports"; print_newline ();
	  Talpp.print_tal_int_type Format.std_formatter Talpp.std_options et;
	  Format.print_newline ()
      	end;
      	if !progc then begin
 	  try
	    Tallinkchk.set_program_interface
	      get_tali (Array.of_list (List.rev !imports)) [|"tal_prog.tali"|];
	    Tallinkchk.verify_program imex;
	    Printf.printf "PROG Verified\n"
	  with
	    Talctxt.Talverify (ctxt,ve) ->
	      print_newline();
	      print_string "PROG verification failed";
	      print_newline ();
	      Talpp.print_Talverify
	      	Format.std_formatter Talpp.std_options (ctxt,ve);
	      Format.print_newline ();
	      raise Talctxt.Talfail
      	end
      with 
      	Talctxt.Talverify (ctxt,ve) ->
	  print_newline();
	  print_string "LINK verification failed";
	  print_newline ();
	  Talpp.print_Talverify
	    Format.std_formatter Talpp.std_options  (ctxt,ve);
	  Format.print_newline ();
	  raise Talctxt.Talfail
    end;
    if libraries<>[] then failwith "Talc.do_link";
    Talout.link objectfiles executable
  with
    Talctxt.Talfail -> false
;;

let toolname = "talc";;
set_tooldesc "TALC: TAL verifier, assembler, link & program verifier";;

let options =
  std_options @
  [ "-S",Arg.String add_std_lib, "add library";
    "--multiple-errors",Arg.Set multiple_errors,
      "show multiple verifier errors";
    "--single-error",Arg.Clear multiple_errors,
      "show first verify error only";
    "--noisy-verify",Arg.Clear silent_verify,
      "indicate verification success";
    "--quite-verify",Arg.Set silent_verify,
      "silent on successful verification";
    "--print-interfaces",Arg.Set print_interfaces,
      "print module interfaces";
    "--no-interfaces",Arg.Clear print_interfaces,
      "do not print module interfaces";
    "--verify-link",Arg.Set linkc,"verify linking";
    "--print-linked-interface",Arg.Set print_linked_interface,
      "print linked interface";
    "--no-linked-interface",Arg.Clear print_linked_interface,
      "do not print linked interface";
    "--verify-program",Arg.Set progc,"verify program";
    "--std-lib",Arg.String add_std_lib, "add library";
  ]
;;

let file_types = [".tal",compile_tal_file] @ std_file_types;;

let main () = driver toolname options file_types middle do_link;;

Printexc.catch main ();;

(* EOF: talc.ml *)
