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

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

let stats = ref false;;
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
      asm filename talm imex objfile;
      add_object_file objfile
    end;
    if !stats then begin
      Talcon.print_stats();
      Gc.print_stat stdout
    end;
    imexs := imex :: !imexs
  with Talctxt.Talfail -> ()
;;

(* Verifies only, doesn't actually link yet *)
let do_link objectfiles libraries executable =
  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 ()
    	| 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 ()
    | Talctxt.Talfail -> ()
  end
;;

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";
    "--stats",Arg.Set stats,"print statsitics"
  ]
;;

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

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

Printexc.catch main ();;

(* EOF: talc.ml *)
