run.ml 4.7 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
  Printf.eprintf "support for expat: %b\n" (Load_xml.expat_support);
16
17
18
19
20
21
22
23
  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
36
    "--stdin", Arg.Unit (fun () -> src := "" :: !src),
           "  read CDuce script on standard input";
37
    "-v", Arg.Unit version,
38
      "       print CDuce version";
39
    "--version", Arg.Unit version,
40
41
42
             "print CDuce version";
    "--license", Arg.Unit license,
             "print CDuce license";
43
   "--arg", Arg.Rest (fun s -> args := s :: !args),
44
         "    following arguments are passed to the CDuce program (in argv)";  
45

46
 ]
47

48
49
50
51
52
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),
53
           "    use PXP parser") ::
54
55
56
57
58
    specs
  else
    specs


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

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

68
69
70

let bol = ref true

71
72
73
let outflush s =
  output_string stdout s;
  flush stdout
74
75

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

115
let do_file s =
116
117
  let chan = open_in s in
  Location.push_source (`File s);
118
  let input = Stream.of_channel chan in
119
120
121
122
123
124
125
  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)
126
127
128
129
    ); 
  let ok = Cduce.script ppf ppf_err input in
  close_in chan;
  if not ok then exit 1
130

131
132
133
134
135
136
137
138
let do_stdin () =
  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

let run s =
  if s = "" then do_stdin () else do_file s
139
140

let main () =
141
  (match !load_dump with
142
143
144
145
146
147
148
149
150
151
     | 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 ...@.")
152
153
154
155
     | None -> 
	 let l = List.rev_map Value.string_latin1 !args in
	 let l = Value.sequence l in
	 let t = Sequence.star Sequence.string in
156
	 Cduce.enter_global_value (ident (U.mk "argv")) l t
157
  );
158
  (match !src with
159
     | [] -> toploop ()
160
     | l -> List.iter run l);
161
  (match !save_dump with
162
163
164
165
166
167
168
169
170
171
     | 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 -> ())



172
173
let () = main ()