File: cmain.ml

package info (click to toggle)
why 2.13-2
  • links: PTS, VCS
  • area: main
  • in suites: lenny
  • size: 12,608 kB
  • ctags: 16,817
  • sloc: ml: 102,672; java: 7,173; ansic: 4,439; makefile: 1,409; sh: 585
file content (219 lines) | stat: -rw-r--r-- 7,619 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
(**************************************************************************)
(*                                                                        *)
(*  The Why platform for program certification                            *)
(*  Copyright (C) 2002-2008                                               *)
(*    Romain BARDOU                                                       *)
(*    Jean-Franois COUCHOT                                               *)
(*    Mehdi DOGGUY                                                        *)
(*    Jean-Christophe FILLITRE                                           *)
(*    Thierry HUBERT                                                      *)
(*    Claude MARCH                                                       *)
(*    Yannick MOY                                                         *)
(*    Christine PAULIN                                                    *)
(*    Yann RGIS-GIANAS                                                   *)
(*    Nicolas ROUSSET                                                     *)
(*    Xavier URBAIN                                                       *)
(*                                                                        *)
(*  This software is free software; you can redistribute it and/or        *)
(*  modify it under the terms of the GNU General Public                   *)
(*  License version 2, as published by the Free Software Foundation.      *)
(*                                                                        *)
(*  This software is distributed in the hope that it will be useful,      *)
(*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *)
(*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                  *)
(*                                                                        *)
(*  See the GNU General Public License version 2 for more details         *)
(*  (enclosed in the file GPL).                                           *)
(*                                                                        *)
(**************************************************************************)

(*i $Id: cmain.ml,v 1.101 2008/02/05 12:10:47 marche Exp $ i*)

open Format
open Coptions
open Cerror
open Creport
open Output

let parse_file f =
  let ppf = Cpp.cpp f in
  let c = open_in ppf in
  let p = Clexer.parse c in
  close_in c;
  f, p

let type_file (f,p) = 
  (f, Ctyping.type_file p)


let main () = 
  let t0 = Unix.times () in
  (* parsing *)
  let input_files = files () in
  let pfiles = List.map parse_file input_files in
  if parse_only then exit 0;
  (* typing *)
  let tfiles = List.map type_file pfiles in
  if type_only then exit 0;
  let on_all_files g = List.map (fun (f, dl) -> (f, g dl)) in
  (* initialisation of global variables *)
  let tfiles = on_all_files Cinit.add_init tfiles in
  (* call graph *)
  List.iter (fun (_,p) -> Cgraph.file p) tfiles ;
  if print_graph then Cprint_graph.print_graph ();
  let tab_comp = Cgraph.find_comp tfiles in
  (* normalisation *)
  Cenv.update_fields_type ();
  lprintf "starting normalization of programs.@.";  
  let nfiles = on_all_files Cnorm.file tfiles in
  (* local aliasing analysis *)
  if local_aliasing then Cptr.local_aliasing_transform ();
  (* separation *)  
  lprintf "starting separation of variables.@.";
  List.iter (fun (_,p) -> Cseparation.file p)  nfiles;
  Cseparation.funct [Cinit.invariants_initially_established_info]; 
  Array.iter (fun l -> 
		Cseparation.funct l ) 
    tab_comp;  
  (* typing predicates *)  
  let nfiles = on_all_files Invariant.add_predicates nfiles in
  if print_norm then begin
    let print_fun = ref true in
    List.iter 
      (fun (f,p) -> 
	 let c = open_out (f ^ "norm") in
	 let fmt = Format.formatter_of_out_channel c in
	 Format.fprintf fmt "/* Declarations */@.@.";
	 Format.fprintf fmt "%a@." Cprint.nfile p;
	 if !print_fun then begin
	   Format.fprintf fmt "/* Functions */@.@.";
	   Cprint.nfunctions fmt;
	   Format.fprintf fmt "@.";
	   print_fun := false;
	 end;
	 close_out c) nfiles;
  end;
  (* effects *)
  lprintf "starting computation of effects.@.";
  List.iter (fun (_,p) -> Ceffect.file p) nfiles;
  Array.iter (Ceffect.effect nfiles) tab_comp;
  Queue.iter 
    (fun (loc,msg) ->
       lprintf "%a %s@." Loc.report_position loc msg;
       warning loc "%s" msg)
    Ceffect.warnings;
  lprintf "heap variables: %a@." Ceffect.print_heap_vars ();
  (* Why interpretation *)
  let why_specs =
    List.fold_left 
      (fun specs (_,f) -> 
	 let s = Cinterp.interp f in s @ specs) 
      [] nfiles
  in
  let (why_code,why_specs) = Cinterp.interp_functions why_specs in
  (* Why specs *)
  let first_file = Filename.chop_extension (List.hd input_files) in
  let file = Lib.file "why" (first_file ^ "_spec") in
  Pp.print_in_file 
    (fun fmt -> 
       fprintf fmt 
	 "(* this file was automatically generated; do not edit *)@\n@\n";
       fprintf fmt "(* zone variables *)@.";
       if Coptions.no_zone_type then
	 fprintf fmt "type global@.@."
       else
	 Hashtbl.iter 
	   (fun name z ->
	      match z.Info.repr with 
		| None ->
		    let d = Type (name,[]) in
		    fprintf fmt "@[%a@]" fprintf_why_decls [d]
		| Some _ -> ())
	   Cenv.zone_table;
       fprintf fmt "(* logic types *)@.";
       Cenv.iter_types (fun t -> fprintf fmt "@[type %s@\n@]" t);

       let why_int_types = 
	 Cinterp.make_int_types_decls () @ Cinterp.make_enum_types_decls ()
       in
       if why_int_types <> [] then begin
	 fprintf fmt "(* C integer types *)@.";
	 Output.fprintf_why_decls fmt why_int_types
       end;

       fprintf fmt "(* heap variables *)@.";
       Hashtbl.iter 
	 (fun v bt -> 
	    let d = Param 
	      (false, v, 
	       Ref_type (Base_type (Info.output_why_type ~quote_var:false 
				      bt.Info.var_why_type))) in
	    fprintf fmt "@[%a@]" fprintf_why_decls [d])
	 Ceffect.heap_vars;
       fprintf fmt "(* functions specifications *)@\n";
       Output.fprintf_why_decls fmt why_specs) 
    (file ^ ".tmp");
  Lib.file_copy_if_different (file ^ ".tmp") (file ^ ".why");
  (* function bodies *)
  if separate then begin
    List.iter
      (fun (f,d) ->
	 Cmake.add first_file f;
	 let file = Lib.file "why" (first_file ^ "__" ^ f ) in
	 Pp.print_in_file 
	   (fun fmt -> Output.fprintf_why_decl fmt d) (file ^ ".tmp");
	 Lib.file_copy_if_different (file ^ ".tmp") (file ^ ".why"))
      why_code
  end else begin
    let file = Lib.file "why" first_file in
    let why_code = List.map snd why_code in
    Pp.print_in_file 
      (fun fmt -> Output.fprintf_why_decls fmt why_code) (file ^ ".tmp");
    Lib.file_copy_if_different (file ^ ".tmp") (file ^ ".why")
  end;
  (* print locs *)
  Pp.print_in_file Cinterp.print_locs (Lib.file "." (first_file ^ ".loc"));
  (* makefile *)
  Cmake.makefile first_file;
  if show_time then
    let t1 = Unix.times () in
    printf "Caduceus execution time : %3.2f@." (t1.Unix.tms_utime -. 
					     t0.Unix.tms_utime)
  else
    ()

       
       
 
let rec explain_exception fmt = function
  | Parsing.Parse_error -> 
      fprintf fmt "Syntax error"
  | Stream.Error s -> 
      fprintf fmt "Syntax error: %s" s
  | Error (Some loc, e) ->
      fprintf fmt "%a%a" Loc.report_position loc report e
  | Error (_, e) ->
      report fmt e
  | e ->
      fprintf fmt "Anomaly: %s@." (Printexc.to_string e);
      raise e


(* for debugging *)

(*
let () = main (); exit 1
*) 

let () =
  try
    main ()
  with e ->
    eprintf "%a@." explain_exception e;
    exit 1

(*
Local Variables: 
compile-command: "make -j -C .. bin/caduceus.byte"
End: 
*)