run.ml 4.56 KB
Newer Older
1
2
open Ident

3
let () = State.close ();;
4

5
6
7
let load_dump = ref None
let save_dump = ref None

8
let src  = ref []
9
let args = ref []
10

11
let version () =
12
13
14
  Printf.eprintf "CDuce, version %s\n" <:symbol<cduce_version>>;
  Printf.eprintf "built on %s\n" <:symbol<build_date>>;
  Printf.eprintf "using OCaml %s compiler\n" <:symbol<ocaml_compiler>>;
15
16
17
18
19
20
21
22
23
  Printf.eprintf "support for expat:%b\n" (Load_xml.expat_support);
  exit 0

let license () =
  Printf.eprintf "\n\
The CDuce interpreter is distributed under the terms of the Q Public \n\
License version 1.0 (included in the sources). The Choice of Law section\n\
been modified from the original Q Public.\n\n
"; 
24
25
  exit 0

26
let specs =
27
28
29
30
31
32
  [ "--load", Arg.String (fun s -> load_dump := Some s), 
          "   load persistency file before running CDuce program";
    "--save", Arg.String (fun s -> save_dump := Some s), 
          "   save persistency file after running CDuce program";
    "--dump", Arg.String (fun s -> save_dump := Some s; load_dump := Some s), 
          "   specify persistency file for loading and saving";
33
34
    "--quiet", Arg.Set Cduce.quiet, 
           "  suppress normal output (typing, results)";
35
    "-v", Arg.Unit version,
36
      "       print CDuce version";
37
    "--version", Arg.Unit version,
38
39
40
             "print CDuce version";
    "--license", Arg.Unit license,
             "print CDuce license";
41
   "--arg", Arg.Rest (fun s -> args := s :: !args),
42
         "    following arguments are passed to the CDuce program (in argv)";  
43

44
 ]
45

46
47
48
49
50
51
52
53
54
55
56
let specs = 
  if Load_xml.expat_support then
    ("--expat", Arg.Unit (fun () -> Load_xml.use_parser := `Expat),
             "  use expat parser (default)") ::
    ("--pxp", Arg.Unit (fun () -> Load_xml.use_parser := `Pxp),
           "    use PXPt parser") ::
    specs
  else
    specs


57
58
let () =
  Arg.parse specs (fun s -> src := s :: !src) 
59
    "\nUsage:\ncduce [OPTIONS ...] [FILE ...] [--arg argument ...]\n\nOptions:"
60

61
let ppf = 
62
  if !Cduce.quiet then Format.formatter_of_buffer (Buffer.create 1023)
63
64
  else Format.std_formatter
let ppf_err = Format.err_formatter
65

66
67
68

let bol = ref true

69
70
71
let outflush s =
  output_string stdout s;
  flush stdout
72
73

let toploop () =
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
  Cduce.toplevel := true;
  let tcio = 
    try Unix.tcgetattr Unix.stdin
    with Unix.Unix_error (_,_,_) -> 
      (* The input is not a terminal *)
      Location.push_source `Stream;
      let input = Stream.of_channel stdin in
      let ok = Cduce.script ppf ppf_err input in
      if not ok then exit 1 else exit 0
  in
  let restore () = 
    Unix.tcsetattr Unix.stdin Unix.TCSADRAIN tcio
  in
  let quit () = 
    outflush "\n";
    restore ();
    exit 0
  in
92
  Format.fprintf ppf "        CDuce version %s\n@." <:symbol<cduce_version>>;
93
94
95
96
97
  Unix.tcsetattr Unix.stdin Unix.TCSADRAIN 
    { tcio with Unix.c_vquit = '\004' };
  Sys.set_signal Sys.sigquit (Sys.Signal_handle (fun _ -> quit ()));
  Sys.catch_break true;
  Cduce.toplevel := true;
98
  Location.push_source `Stream;
99
  let read i =
100
101
    if !bol then 
      if !Wlexer.in_comment then outflush "* " else outflush "> ";
102
103
104
105
106
107
    try 
      let c = input_char stdin in
      bol := c = '\n';
      Some c
    with Sys.Break -> quit () 
  in
108
109
  let input = Stream.from read in
  let rec loop () =
110
111
112
113
    outflush "# ";
    bol := false;
    ignore (Cduce.topinput ppf ppf_err input);
    while (input_char stdin != '\n') do () done;
114
    loop () in
115
116
  (try loop () with End_of_file -> ());
  restore ()
117

118
let do_file s =
119
120
  let chan = open_in s in
  Location.push_source (`File s);
121
  let input = Stream.of_channel chan in
122
123
124
125
126
127
128
  if Stream.peek input = Some '#' then
    (
      let rec count n =
	match Stream.next input with
	  | '\n' -> n
	  | _ -> count (n + 1) in
      Wlexer.set_delta_loc (count 1)
129
130
131
132
    ); 
  let ok = Cduce.script ppf ppf_err input in
  close_in chan;
  if not ok then exit 1
133
134
135
136

  

let main () =
137
  (match !load_dump with
138
139
140
141
142
143
144
145
146
147
     | Some f ->
	 (try 
	    Format.fprintf ppf "Restoring state: ";
	    let chan = open_in_bin f in
	    let s = Marshal.from_channel chan in
	    close_in chan;
	    State.set s;
	    Format.fprintf ppf "done ...@."
	  with Sys_error _ ->  
	    Format.fprintf ppf "failed ...@.")
148
149
150
151
     | None -> 
	 let l = List.rev_map Value.string_latin1 !args in
	 let l = Value.sequence l in
	 let t = Sequence.star Sequence.string in
152
	 Cduce.enter_global_value (ident (U.mk "argv")) l t
153
  );
154
  (match !src with
155
     | [] -> toploop ()
156
     | l -> List.iter do_file l);
157
  (match !save_dump with
158
159
160
161
162
163
164
165
166
167
     | Some f ->
	 Format.fprintf ppf "Saving state ...@\n";
	 let s = State.get () in
	 let chan = open_out_bin f in
	 Marshal.to_channel chan s [ Marshal.Closures ];
	 close_out chan
     | None -> ())



168
169
let () = main ()