(* $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
;;