|
Packit |
bd2e5d |
(***********************************************************************)
|
|
Packit |
bd2e5d |
(* *)
|
|
Packit |
bd2e5d |
(* MLTk, Tcl/Tk interface of OCaml *)
|
|
Packit |
bd2e5d |
(* *)
|
|
Packit |
bd2e5d |
(* Francois Rouaix, Francois Pessaux, Jun Furuse and Pierre Weis *)
|
|
Packit |
bd2e5d |
(* projet Cristal, INRIA Rocquencourt *)
|
|
Packit |
bd2e5d |
(* Jacques Garrigue, Kyoto University RIMS *)
|
|
Packit |
bd2e5d |
(* *)
|
|
Packit |
bd2e5d |
(* Copyright 2002 Institut National de Recherche en Informatique et *)
|
|
Packit |
bd2e5d |
(* en Automatique and Kyoto University. All rights reserved. *)
|
|
Packit |
bd2e5d |
(* This file is distributed under the terms of the GNU Library *)
|
|
Packit |
bd2e5d |
(* General Public License, with the special exception on linking *)
|
|
Packit |
bd2e5d |
(* described in file LICENSE found in the OCaml source tree. *)
|
|
Packit |
bd2e5d |
(* *)
|
|
Packit |
bd2e5d |
(***********************************************************************)
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(* $Id$ *)
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
open StdLabels
|
|
Packit |
bd2e5d |
open Tables
|
|
Packit |
bd2e5d |
open Printer
|
|
Packit |
bd2e5d |
open Compile
|
|
Packit |
bd2e5d |
open Intf
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let flag_verbose = ref false
|
|
Packit |
bd2e5d |
let verbose_string s =
|
|
Packit |
bd2e5d |
if !flag_verbose then prerr_string s
|
|
Packit |
bd2e5d |
let verbose_endline s =
|
|
Packit |
bd2e5d |
if !flag_verbose then prerr_endline s
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let input_name = ref "Widgets.src"
|
|
Packit |
bd2e5d |
let output_dir = ref ""
|
|
Packit |
bd2e5d |
let destfile f = Filename.concat !output_dir f
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let usage () =
|
|
Packit |
bd2e5d |
prerr_string "Usage: tkcompiler input.src\n";
|
|
Packit |
bd2e5d |
flush stderr;
|
|
Packit |
bd2e5d |
exit 1
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let prerr_error_header () =
|
|
Packit |
bd2e5d |
prerr_string "File \""; prerr_string !input_name;
|
|
Packit |
bd2e5d |
prerr_string "\", line ";
|
|
Packit |
bd2e5d |
prerr_string (string_of_int !Lexer.current_line);
|
|
Packit |
bd2e5d |
prerr_string ": "
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(* parse Widget.src config file *)
|
|
Packit |
bd2e5d |
let parse_file filename =
|
|
Packit |
bd2e5d |
let ic = open_in_bin filename in
|
|
Packit |
bd2e5d |
let lexbuf =
|
|
Packit |
bd2e5d |
try
|
|
Packit |
bd2e5d |
let code_list = Ppparse.parse_channel ic in
|
|
Packit |
bd2e5d |
close_in ic;
|
|
Packit |
bd2e5d |
let buf = Buffer.create 50000 in
|
|
Packit |
bd2e5d |
List.iter (Ppexec.exec
|
|
Packit |
bd2e5d |
(fun l -> Buffer.add_string buf
|
|
Packit |
bd2e5d |
(Printf.sprintf "##line %d\n" l))
|
|
Packit |
bd2e5d |
(Buffer.add_string buf))
|
|
Packit |
bd2e5d |
(if !Flags.camltk then Code.Define "CAMLTK" :: code_list
|
|
Packit |
bd2e5d |
else code_list);
|
|
Packit |
bd2e5d |
Lexing.from_string (Buffer.contents buf)
|
|
Packit |
bd2e5d |
with
|
|
Packit |
bd2e5d |
| Ppparse.Error s ->
|
|
Packit |
bd2e5d |
close_in ic;
|
|
Packit |
bd2e5d |
raise (Compiler_Error (Printf.sprintf "Preprocess error: %s" s))
|
|
Packit |
bd2e5d |
in
|
|
Packit |
bd2e5d |
try
|
|
Packit |
bd2e5d |
while true do
|
|
Packit |
bd2e5d |
Parser.entry Lexer.main lexbuf
|
|
Packit |
bd2e5d |
done
|
|
Packit |
bd2e5d |
with
|
|
Packit |
bd2e5d |
| Parsing.Parse_error ->
|
|
Packit |
bd2e5d |
prerr_error_header();
|
|
Packit |
bd2e5d |
prerr_string "Syntax error \n";
|
|
Packit |
bd2e5d |
exit 1
|
|
Packit |
bd2e5d |
| Lexer.Lexical_error s ->
|
|
Packit |
bd2e5d |
prerr_error_header();
|
|
Packit |
bd2e5d |
prerr_string "Lexical error (";
|
|
Packit |
bd2e5d |
prerr_string s;
|
|
Packit |
bd2e5d |
prerr_string ")\n";
|
|
Packit |
bd2e5d |
exit 1
|
|
Packit |
bd2e5d |
| Duplicate_Definition (s,s') ->
|
|
Packit |
bd2e5d |
prerr_error_header();
|
|
Packit |
bd2e5d |
prerr_string s; prerr_string " "; prerr_string s';
|
|
Packit |
bd2e5d |
prerr_string " is defined twice.\n";
|
|
Packit |
bd2e5d |
exit 1
|
|
Packit |
bd2e5d |
| Compiler_Error s ->
|
|
Packit |
bd2e5d |
prerr_error_header();
|
|
Packit |
bd2e5d |
prerr_string "Internal error: "; prerr_string s; prerr_string "\n";
|
|
Packit |
bd2e5d |
prerr_string "Please report bug\n";
|
|
Packit |
bd2e5d |
exit 1
|
|
Packit |
bd2e5d |
| End_of_file ->
|
|
Packit |
bd2e5d |
()
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(* The hack to provoke the production of cCAMLtoTKoptions_constrs *)
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(* Auxiliary function: the list of all the elements associated to keys
|
|
Packit |
bd2e5d |
in an hash table. *)
|
|
Packit |
bd2e5d |
let elements t =
|
|
Packit |
bd2e5d |
let elems = ref [] in
|
|
Packit |
bd2e5d |
Hashtbl.iter (fun _ d -> elems := d :: !elems) t;
|
|
Packit |
bd2e5d |
!elems;;
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(* Verifies that duplicated clauses are semantically equivalent and
|
|
Packit |
bd2e5d |
returns a unique set of clauses. *)
|
|
Packit |
bd2e5d |
let uniq_clauses = function
|
|
Packit |
bd2e5d |
| [] -> []
|
|
Packit |
bd2e5d |
| l ->
|
|
Packit |
bd2e5d |
let check_constr constr1 constr2 =
|
|
Packit |
bd2e5d |
if constr1.template <> constr2.template then
|
|
Packit |
bd2e5d |
begin
|
|
Packit |
bd2e5d |
let code1, vars11, vars12, opts1 =
|
|
Packit |
bd2e5d |
code_of_template ~context_widget:"dummy" constr1.template in
|
|
Packit |
bd2e5d |
let code2, vars12, vars22, opts2 =
|
|
Packit |
bd2e5d |
code_of_template ~context_widget:"dummy" constr2.template in
|
|
Packit |
bd2e5d |
let err =
|
|
Packit |
bd2e5d |
Printf.sprintf
|
|
Packit |
bd2e5d |
"uncompatible redondant clauses for variant %s:\n %s\n and\n %s"
|
|
Packit |
bd2e5d |
constr1.var_name code1 code2 in
|
|
Packit |
bd2e5d |
Format.print_newline();
|
|
Packit |
bd2e5d |
print_fullcomponent constr1;
|
|
Packit |
bd2e5d |
Format.print_newline();
|
|
Packit |
bd2e5d |
print_fullcomponent constr2;
|
|
Packit |
bd2e5d |
Format.print_newline();
|
|
Packit |
bd2e5d |
prerr_endline err;
|
|
Packit |
bd2e5d |
fatal_error err
|
|
Packit |
bd2e5d |
end in
|
|
Packit |
bd2e5d |
let t = Hashtbl.create 11 in
|
|
Packit |
bd2e5d |
List.iter l
|
|
Packit |
bd2e5d |
~f:(fun constr ->
|
|
Packit |
bd2e5d |
let c = constr.var_name in
|
|
Packit |
bd2e5d |
if Hashtbl.mem t c
|
|
Packit |
bd2e5d |
then (check_constr constr (Hashtbl.find t c))
|
|
Packit |
bd2e5d |
else Hashtbl.add t c constr);
|
|
Packit |
bd2e5d |
elements t;;
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let option_hack oc =
|
|
Packit |
bd2e5d |
if Hashtbl.mem types_table "options" then
|
|
Packit |
bd2e5d |
let typdef = Hashtbl.find types_table "options" in
|
|
Packit |
bd2e5d |
let hack =
|
|
Packit |
bd2e5d |
{ parser_arity = OneToken;
|
|
Packit |
bd2e5d |
constructors = begin
|
|
Packit |
bd2e5d |
let constrs =
|
|
Packit |
bd2e5d |
List.map typdef.constructors ~f:
|
|
Packit |
bd2e5d |
begin fun c ->
|
|
Packit |
bd2e5d |
{ component = Constructor;
|
|
Packit |
bd2e5d |
ml_name = (if !Flags.camltk then "C" ^ c.ml_name
|
|
Packit |
bd2e5d |
else c.ml_name);
|
|
Packit |
bd2e5d |
var_name = c.var_name; (* as variants *)
|
|
Packit |
bd2e5d |
template =
|
|
Packit |
bd2e5d |
begin match c.template with
|
|
Packit |
bd2e5d |
ListArg (x :: _) -> x
|
|
Packit |
bd2e5d |
| _ -> fatal_error "bogus hack"
|
|
Packit |
bd2e5d |
end;
|
|
Packit |
bd2e5d |
result = UserDefined "options_constrs";
|
|
Packit |
bd2e5d |
safe = true }
|
|
Packit |
bd2e5d |
end in
|
|
Packit |
bd2e5d |
if !Flags.camltk then constrs else uniq_clauses constrs (* JPF ?? *)
|
|
Packit |
bd2e5d |
end;
|
|
Packit |
bd2e5d |
subtypes = [];
|
|
Packit |
bd2e5d |
requires_widget_context = false;
|
|
Packit |
bd2e5d |
variant = false }
|
|
Packit |
bd2e5d |
in
|
|
Packit |
bd2e5d |
write_CAMLtoTK
|
|
Packit |
bd2e5d |
~w:(output_string oc) ~def:hack ~safetype:false "options_constrs"
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let realname name =
|
|
Packit |
bd2e5d |
(* module name fix for camltk *)
|
|
Packit |
bd2e5d |
let name = caml_name name in
|
|
Packit |
bd2e5d |
if !Flags.camltk then "c" ^ String.capitalize_ascii name
|
|
Packit |
bd2e5d |
else name
|
|
Packit |
bd2e5d |
;;
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(* analize the parsed Widget.src and output source files *)
|
|
Packit |
bd2e5d |
let compile () =
|
|
Packit |
bd2e5d |
verbose_endline "Creating _tkgen.ml ...";
|
|
Packit |
bd2e5d |
let oc = open_out_bin (destfile "_tkgen.ml") in
|
|
Packit |
bd2e5d |
let oc' = open_out_bin (destfile "_tkigen.ml") in
|
|
Packit |
bd2e5d |
let oc'' = open_out_bin (destfile "_tkfgen.ml") in
|
|
Packit |
bd2e5d |
let sorted_types = Tsort.sort types_order in
|
|
Packit |
bd2e5d |
verbose_endline " writing types ...";
|
|
Packit |
bd2e5d |
List.iter sorted_types ~f:
|
|
Packit |
bd2e5d |
begin fun typname ->
|
|
Packit |
bd2e5d |
verbose_string (" " ^ typname ^ " ");
|
|
Packit |
bd2e5d |
try
|
|
Packit |
bd2e5d |
let typdef = Hashtbl.find types_table typname in
|
|
Packit |
bd2e5d |
verbose_string "type ";
|
|
Packit |
bd2e5d |
write_type ~intf:(output_string oc)
|
|
Packit |
bd2e5d |
~impl:(output_string oc')
|
|
Packit |
bd2e5d |
typname ~def:typdef;
|
|
Packit |
bd2e5d |
verbose_string "C2T ";
|
|
Packit |
bd2e5d |
write_CAMLtoTK ~w:(output_string oc') typname ~def:typdef;
|
|
Packit |
bd2e5d |
verbose_string "T2C ";
|
|
Packit |
bd2e5d |
if List.mem typname !types_returned then
|
|
Packit |
bd2e5d |
write_TKtoCAML ~w:(output_string oc') typname ~def:typdef;
|
|
Packit |
bd2e5d |
verbose_string "CO ";
|
|
Packit |
bd2e5d |
if not !Flags.camltk then (* only for LablTk *)
|
|
Packit |
bd2e5d |
write_catch_optionals ~w:(output_string oc') typname ~def:typdef;
|
|
Packit |
bd2e5d |
verbose_endline "."
|
|
Packit |
bd2e5d |
with Not_found ->
|
|
Packit |
bd2e5d |
if not (List.mem_assoc typname !types_external) then
|
|
Packit |
bd2e5d |
begin
|
|
Packit |
bd2e5d |
verbose_string "Type ";
|
|
Packit |
bd2e5d |
verbose_string typname;
|
|
Packit |
bd2e5d |
verbose_string " is undeclared external or undefined\n"
|
|
Packit |
bd2e5d |
end
|
|
Packit |
bd2e5d |
else verbose_endline "."
|
|
Packit |
bd2e5d |
end;
|
|
Packit |
bd2e5d |
verbose_endline " option hacking ...";
|
|
Packit |
bd2e5d |
option_hack oc';
|
|
Packit |
bd2e5d |
verbose_endline " writing functions ...";
|
|
Packit |
bd2e5d |
List.iter ~f:(write_function ~w:(output_string oc'')) !function_table;
|
|
Packit |
bd2e5d |
close_out oc;
|
|
Packit |
bd2e5d |
close_out oc';
|
|
Packit |
bd2e5d |
close_out oc'';
|
|
Packit |
bd2e5d |
(* Write the interface for public functions *)
|
|
Packit |
bd2e5d |
(* this interface is used only for documentation *)
|
|
Packit |
bd2e5d |
verbose_endline "Creating _tkgen.mli ...";
|
|
Packit |
bd2e5d |
let oc = open_out_bin (destfile "_tkgen.mli") in
|
|
Packit |
bd2e5d |
List.iter (sort_components !function_table)
|
|
Packit |
bd2e5d |
~f:(write_function_type ~w:(output_string oc));
|
|
Packit |
bd2e5d |
close_out oc;
|
|
Packit |
bd2e5d |
verbose_endline "Creating other ml, mli ...";
|
|
Packit |
bd2e5d |
let write_module wname wdef =
|
|
Packit |
bd2e5d |
verbose_endline (" "^wname);
|
|
Packit |
bd2e5d |
let modname = realname wname in
|
|
Packit |
bd2e5d |
let oc = open_out_bin (destfile (modname ^ ".ml"))
|
|
Packit |
bd2e5d |
and oc' = open_out_bin (destfile (modname ^ ".mli")) in
|
|
Packit |
bd2e5d |
Copyright.write ~w:(output_string oc);
|
|
Packit |
bd2e5d |
Copyright.write ~w:(output_string oc');
|
|
Packit |
bd2e5d |
begin match wdef.module_type with
|
|
Packit |
bd2e5d |
Widget -> output_string oc' ("(** The "^wname^" widget *)\n")
|
|
Packit |
bd2e5d |
| Family -> output_string oc' ("(** The "^wname^" commands *)\n")
|
|
Packit |
bd2e5d |
end;
|
|
Packit |
bd2e5d |
List.iter ~f:(fun s -> output_string oc s; output_string oc' s)
|
|
Packit |
bd2e5d |
begin
|
|
Packit |
bd2e5d |
if !Flags.camltk then
|
|
Packit |
bd2e5d |
[ "open CTk\n";
|
|
Packit |
bd2e5d |
"open Tkintf\n";
|
|
Packit |
bd2e5d |
"open Widget\n";
|
|
Packit |
bd2e5d |
"open Textvariable\n\n" ]
|
|
Packit |
bd2e5d |
else
|
|
Packit |
bd2e5d |
[ "open StdLabels\n";
|
|
Packit |
bd2e5d |
"open Tk\n";
|
|
Packit |
bd2e5d |
"open Tkintf\n";
|
|
Packit |
bd2e5d |
"open Widget\n";
|
|
Packit |
bd2e5d |
"open Textvariable\n\n" ]
|
|
Packit |
bd2e5d |
end;
|
|
Packit |
bd2e5d |
output_string oc "open Protocol\n";
|
|
Packit |
bd2e5d |
begin match wdef.module_type with
|
|
Packit |
bd2e5d |
Widget ->
|
|
Packit |
bd2e5d |
if !Flags.camltk then begin
|
|
Packit |
bd2e5d |
camltk_write_create ~w:(output_string oc) wname;
|
|
Packit |
bd2e5d |
camltk_write_named_create ~w:(output_string oc) wname;
|
|
Packit |
bd2e5d |
camltk_write_create_p ~w:(output_string oc') wname;
|
|
Packit |
bd2e5d |
camltk_write_named_create_p ~w:(output_string oc') wname;
|
|
Packit |
bd2e5d |
end else begin
|
|
Packit |
bd2e5d |
labltk_write_create ~w:(output_string oc) wname;
|
|
Packit |
bd2e5d |
labltk_write_create_p ~w:(output_string oc') wname
|
|
Packit |
bd2e5d |
end
|
|
Packit |
bd2e5d |
| Family -> ()
|
|
Packit |
bd2e5d |
end;
|
|
Packit |
bd2e5d |
List.iter ~f:(write_function ~w:(output_string oc))
|
|
Packit |
bd2e5d |
(sort_components wdef.commands);
|
|
Packit |
bd2e5d |
List.iter ~f:(write_function_type ~w:(output_string oc'))
|
|
Packit |
bd2e5d |
(sort_components wdef.commands);
|
|
Packit |
bd2e5d |
List.iter ~f:(write_external ~w:(output_string oc))
|
|
Packit |
bd2e5d |
(sort_components wdef.externals);
|
|
Packit |
bd2e5d |
List.iter ~f:(write_external_type ~w:(output_string oc'))
|
|
Packit |
bd2e5d |
(sort_components wdef.externals);
|
|
Packit |
bd2e5d |
close_out oc;
|
|
Packit |
bd2e5d |
close_out oc'
|
|
Packit |
bd2e5d |
in Hashtbl.iter write_module module_table;
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(* wrapper code camltk.ml and labltk.ml *)
|
|
Packit |
bd2e5d |
if !Flags.camltk then begin
|
|
Packit |
bd2e5d |
let oc = open_out_bin (destfile "camltk.ml") in
|
|
Packit |
bd2e5d |
Copyright.write ~w:(output_string oc);
|
|
Packit |
bd2e5d |
output_string oc
|
|
Packit |
bd2e5d |
"(** This module Camltk provides the module name spaces of the CamlTk API.\n\
|
|
Packit |
bd2e5d |
\n\
|
|
Packit |
bd2e5d |
The users of the CamlTk API should open this module first to access\n\
|
|
Packit |
bd2e5d |
the types, functions and modules of the CamlTk API easier.\n\
|
|
Packit |
bd2e5d |
For the documentation of each sub modules such as [Button] and [Toplevel],\n\
|
|
Packit |
bd2e5d |
refer to its defintion file, [cButton.mli], [cToplevel.mli], etc.\n\
|
|
Packit |
bd2e5d |
*)\n\
|
|
Packit |
bd2e5d |
\n\
|
|
Packit |
bd2e5d |
";
|
|
Packit |
bd2e5d |
output_string oc "include CTk\n";
|
|
Packit |
bd2e5d |
output_string oc "module Tk = CTk\n";
|
|
Packit |
bd2e5d |
Hashtbl.iter (fun name _ ->
|
|
Packit |
bd2e5d |
let cname = realname name in
|
|
Packit |
bd2e5d |
output_string oc (Printf.sprintf "module %s = %s;;\n"
|
|
Packit |
bd2e5d |
(String.capitalize_ascii (caml_name name))
|
|
Packit |
bd2e5d |
(String.capitalize_ascii cname))) module_table;
|
|
Packit |
bd2e5d |
close_out oc
|
|
Packit |
bd2e5d |
end else begin
|
|
Packit |
bd2e5d |
let oc = open_out_bin (destfile "labltk.ml") in
|
|
Packit |
bd2e5d |
Copyright.write ~w:(output_string oc);
|
|
Packit |
bd2e5d |
output_string oc
|
|
Packit |
bd2e5d |
"(** This module Labltk provides the module name spaces of the LablTk API,\n\
|
|
Packit |
bd2e5d |
useful to call LablTk functions inside CamlTk programs. 100% LablTk users\n\
|
|
Packit |
bd2e5d |
do not need to use this. *)\n\
|
|
Packit |
bd2e5d |
\n\
|
|
Packit |
bd2e5d |
";
|
|
Packit |
bd2e5d |
output_string oc "module Widget = Widget;;\n\
|
|
Packit |
bd2e5d |
module Protocol = Protocol;;\n\
|
|
Packit |
bd2e5d |
module Textvariable = Textvariable;;\n\
|
|
Packit |
bd2e5d |
module Fileevent = Fileevent;;\n\
|
|
Packit |
bd2e5d |
module Timer = Timer;;\n\
|
|
Packit |
bd2e5d |
";
|
|
Packit |
bd2e5d |
Hashtbl.iter (fun name _ ->
|
|
Packit |
bd2e5d |
let cname = realname name in
|
|
Packit |
bd2e5d |
output_string oc (Printf.sprintf "module %s = %s;;\n"
|
|
Packit |
bd2e5d |
(String.capitalize_ascii (caml_name name))
|
|
Packit |
bd2e5d |
(String.capitalize_ascii cname))) module_table;
|
|
Packit |
bd2e5d |
(* widget typer *)
|
|
Packit |
bd2e5d |
output_string oc "\n(** Widget typers *)\n\nopen Widget\n\n";
|
|
Packit |
bd2e5d |
Hashtbl.iter (fun name def ->
|
|
Packit |
bd2e5d |
match def.module_type with
|
|
Packit |
bd2e5d |
| Widget ->
|
|
Packit |
bd2e5d |
let name = caml_name name in
|
|
Packit |
bd2e5d |
output_string oc (Printf.sprintf
|
|
Packit |
bd2e5d |
"let %s (w : any widget) =\n" name);
|
|
Packit |
bd2e5d |
output_string oc (Printf.sprintf
|
|
Packit |
bd2e5d |
" Rawwidget.check_class w widget_%s_table;\n" name);
|
|
Packit |
bd2e5d |
output_string oc (Printf.sprintf
|
|
Packit |
bd2e5d |
" (Obj.magic w : %s widget);;\n\n" name);
|
|
Packit |
bd2e5d |
| _ -> () ) module_table;
|
|
Packit |
bd2e5d |
close_out oc
|
|
Packit |
bd2e5d |
end;
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(* write the module list for the Makefile *)
|
|
Packit |
bd2e5d |
(* and hack to death until it works *)
|
|
Packit |
bd2e5d |
let oc = open_out_bin (destfile "modules") in
|
|
Packit |
bd2e5d |
if !Flags.camltk then output_string oc "CWIDGETOBJS="
|
|
Packit |
bd2e5d |
else output_string oc "WIDGETOBJS=";
|
|
Packit |
bd2e5d |
Hashtbl.iter
|
|
Packit |
bd2e5d |
(fun name _ ->
|
|
Packit |
bd2e5d |
let name = realname name in
|
|
Packit |
bd2e5d |
output_string oc " ";
|
|
Packit |
bd2e5d |
output_string oc name;
|
|
Packit |
bd2e5d |
output_string oc ".cmo")
|
|
Packit |
bd2e5d |
module_table;
|
|
Packit |
bd2e5d |
output_string oc "\n";
|
|
Packit |
bd2e5d |
Hashtbl.iter
|
|
Packit |
bd2e5d |
(fun name _ ->
|
|
Packit |
bd2e5d |
let name = realname name in
|
|
Packit |
bd2e5d |
output_string oc name;
|
|
Packit |
bd2e5d |
output_string oc ".ml ")
|
|
Packit |
bd2e5d |
module_table;
|
|
Packit |
bd2e5d |
output_string oc ": _tkgen.ml\n\n";
|
|
Packit |
bd2e5d |
Hashtbl.iter
|
|
Packit |
bd2e5d |
(fun name _ ->
|
|
Packit |
bd2e5d |
let name = realname name in
|
|
Packit |
bd2e5d |
output_string oc name;
|
|
Packit |
bd2e5d |
output_string oc ".cmo : ";
|
|
Packit |
bd2e5d |
output_string oc name;
|
|
Packit |
bd2e5d |
output_string oc ".ml\n";
|
|
Packit |
bd2e5d |
output_string oc name;
|
|
Packit |
bd2e5d |
output_string oc ".cmi : ";
|
|
Packit |
bd2e5d |
output_string oc name;
|
|
Packit |
bd2e5d |
output_string oc ".mli\n")
|
|
Packit |
bd2e5d |
module_table;
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(* for camltk.ml wrapper *)
|
|
Packit |
bd2e5d |
if !Flags.camltk then begin
|
|
Packit |
bd2e5d |
output_string oc "camltk.cmo : cTk.cmo ";
|
|
Packit |
bd2e5d |
Hashtbl.iter
|
|
Packit |
bd2e5d |
(fun name _ ->
|
|
Packit |
bd2e5d |
let name = realname name in
|
|
Packit |
bd2e5d |
output_string oc name;
|
|
Packit |
bd2e5d |
output_string oc ".cmo ") module_table;
|
|
Packit |
bd2e5d |
output_string oc "\n"
|
|
Packit |
bd2e5d |
end;
|
|
Packit |
bd2e5d |
close_out oc
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let main () =
|
|
Packit |
bd2e5d |
Arg.parse
|
|
Packit |
bd2e5d |
[ "-verbose", Arg.Unit (fun () -> flag_verbose := true),
|
|
Packit |
bd2e5d |
"Make output verbose";
|
|
Packit |
bd2e5d |
"-camltk", Arg.Unit (fun () -> Flags.camltk := true),
|
|
Packit |
bd2e5d |
"Make CamlTk interface";
|
|
Packit |
bd2e5d |
"-outdir", Arg.String (fun s -> output_dir := s),
|
|
Packit |
bd2e5d |
"output directory";
|
|
Packit |
bd2e5d |
"-debugpp", Arg.Unit (fun () -> Ppexec.debug := true),
|
|
Packit |
bd2e5d |
"debug preprocessor"
|
|
Packit |
bd2e5d |
]
|
|
Packit |
bd2e5d |
(fun filename -> input_name := filename)
|
|
Packit |
bd2e5d |
"Usage: tkcompiler <source file>" ;
|
|
Packit |
bd2e5d |
if !output_dir = "" then begin
|
|
Packit |
bd2e5d |
prerr_endline "specify -outdir option";
|
|
Packit |
bd2e5d |
exit 1
|
|
Packit |
bd2e5d |
end;
|
|
Packit |
bd2e5d |
try
|
|
Packit |
bd2e5d |
verbose_endline "Parsing...";
|
|
Packit |
bd2e5d |
parse_file !input_name;
|
|
Packit |
bd2e5d |
verbose_endline "Compiling...";
|
|
Packit |
bd2e5d |
compile ();
|
|
Packit |
bd2e5d |
verbose_endline "Finished";
|
|
Packit |
bd2e5d |
exit 0
|
|
Packit |
bd2e5d |
with
|
|
Packit |
bd2e5d |
| Lexer.Lexical_error s ->
|
|
Packit |
bd2e5d |
prerr_string "Invalid lexical character: ";
|
|
Packit |
bd2e5d |
prerr_endline s;
|
|
Packit |
bd2e5d |
exit 1
|
|
Packit |
bd2e5d |
| Duplicate_Definition (s, s') ->
|
|
Packit |
bd2e5d |
prerr_string s; prerr_string " "; prerr_string s';
|
|
Packit |
bd2e5d |
prerr_endline " is redefined illegally";
|
|
Packit |
bd2e5d |
exit 1
|
|
Packit |
bd2e5d |
| Invalid_implicit_constructor c ->
|
|
Packit |
bd2e5d |
prerr_string "Constructor ";
|
|
Packit |
bd2e5d |
prerr_string c;
|
|
Packit |
bd2e5d |
prerr_endline " is used implicitly before defined";
|
|
Packit |
bd2e5d |
exit 1
|
|
Packit |
bd2e5d |
| Tsort.Cyclic ->
|
|
Packit |
bd2e5d |
prerr_endline "Cyclic dependency of types";
|
|
Packit |
bd2e5d |
exit 1
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let () = Printexc.catch main ()
|