Plasma GitLab Archive
Projects Blog Knowledge

(* $Id: hgen_main.ml 20579 2009-03-27 17:54:33Z gerd $ *)

open Hgen_types;;

let initial_comment f name =
  Printf.fprintf f
    ("(************************************************************\n\
   \032* WARNING!\n\
   \032*\n\
   \032* This file is generated by hydrogen from the source file\n\
   \032* %s\n\
   \032*\n\
   \032************************************************************)\n%!")
    name


let main() =
  let filename = ref "" in
  let p_symtable = ref false in
  let view = ref false in
  let cpp = ref (Some "cpp") in
  let cpp_options = ref [] in

  Arg.parse
    [ "-print-symboltable", Arg.Set p_symtable,
      "  Print the symbol table after parsing";

      "-view", Arg.Set view,
      "  Only print the MLI and ML files to generate to stdout";

      "-dm", Arg.Set Hgen_trans_il.enable_directmapping,
      "  Enable that DirectMapping code is generated (faster but more code)";

      "-cpp", (Arg.String
                 (fun s ->
                    cpp := if s = "none" then None else Some s)),
      "<p> Call the command <p> as preprocessor (-cpp none disables)";

      "-D", (Arg.String (fun s -> cpp_options := !cpp_options @ [ "-D" ^ s ])),
      "var=value Define the preprocessor variable var";

      "-U", (Arg.String (fun s -> cpp_options := !cpp_options @ [ "-U" ^ s ])),
      "var Undefine the preprocessor variable var";
    ]
    (fun s ->
       filename := s
    )
    (Printf.sprintf "usage: %s [options] file.ice" (Filename.basename Sys.argv.(0)));

  if !filename = "" then
    failwith "No filename given";

  let f, close_f =
    match !cpp with
      | None ->
	  let f = open_in !filename in
	  (f, (fun () -> close_in f) )
      | Some cmd ->
          let options =
            String.concat " " (List.map Filename.quote !cpp_options) in
          let f = 
	    Unix.open_process_in (cmd ^ " " ^ options ^ " " ^ !filename) in
	  let to_close = ref true in
	  (f, (fun () -> 
		 if !to_close then (
		   let status = Unix.close_process_in f in
		   to_close := false;
		   if status <> Unix.WEXITED 0 then
		     failwith "Preprocessor failed"
		 )
	      )
	  )
  in

  let onerror = ref [close_f] in

  try
    let defs = Hgen_analyzer.parse !filename f in
    let symtab = Hgen_analyzer.analyze defs in
    close_f();

    if !p_symtable then
      Hgen_util.TS_util.print_symboltable symtab;
    
    let pad = Hgen_trans_il.to_il symtab in
    
    if !view then (
      let fmt = Format.std_formatter in
      print_string "(**********************************************************************)\n";
      print_string "(* MLI                                                                *)\n";
      print_string "(**********************************************************************)\n";
      Hgen_print_il.print_pad_sig fmt pad;
      print_string "(**********************************************************************)\n";
      print_string "(* ML                                                                 *)\n";
      print_string "(**********************************************************************)\n";
      Hgen_print_il.print_pad_impl fmt pad
    )
    else (
      let basename = Filename.chop_extension !filename in
      let mliname = basename ^ ".mli" in
      let mli = open_out mliname in
      onerror := 
	(fun () -> close_out mli; Sys.remove mliname) ::
	  !onerror;
      initial_comment mli !filename;
      let mli_fmt = Format.formatter_of_out_channel mli in
      Hgen_print_il.print_pad_sig mli_fmt pad;
      Format.pp_print_flush mli_fmt ();
      close_out mli;
      
      let mlname = basename ^ ".ml" in
      let ml = open_out mlname in
      onerror := 
	(fun () -> close_out ml; Sys.remove mlname) ::
	  !onerror;
      initial_comment ml !filename;
      let ml_fmt = Format.formatter_of_out_channel ml in
      Hgen_print_il.print_pad_impl ml_fmt pad;
      Format.pp_print_flush ml_fmt ();
      close_out ml;
    );
    close_f()
  with
    | err -> List.iter (fun f -> try f() with _ -> ()) !onerror; raise err
;;



let loc_string loc =
  Printf.sprintf "File %s, line %d, column %d"
    loc.file
    loc.line
    (loc.offset - loc.bol)
;;


try
  main()
with
  | Hgen_types.Lexical_error(loc,msg) ->
      Printf.eprintf "%s: Lexical error: %s\n%!" (loc_string loc) msg;
      exit 2
  | Hgen_types.Syntax_error loc ->
      Printf.eprintf "%s: Syntax error\n%!" (loc_string loc);
      exit 2
  | Hgen_types.Other_error(loc,msg) ->
      Printf.eprintf "%s: %s\n%!" (loc_string loc) msg;
      exit 2
  | Hgen_types.Noloc_error msg ->
      Printf.eprintf "At unknown location: %s\n%!" msg;
      exit 2
;;

This web site is published by Informatikbüro Gerd Stolpmann
Powered by Caml