diff --git a/src/kernel_services/cmdline_parameters/parameter_sig.mli b/src/kernel_services/cmdline_parameters/parameter_sig.mli index 060ea5842489ddacd0c62b317e5f6ad4852c9880..4906addb8276c4ef313be7fbd09c7f76b575709d 100644 --- a/src/kernel_services/cmdline_parameters/parameter_sig.mli +++ b/src/kernel_services/cmdline_parameters/parameter_sig.mli @@ -295,33 +295,19 @@ module type Filepath = S with type t = Filepath.Normalized.t (** signature for searching files in a specific directory. *) module type Specific_dir = sig - exception No_dir - - val force_dir: bool - (** For functions below: if [force_dir] is true: if [error] is [false], then - creates the directory if it does not exist (or raises No_dir if the - directory cannot be created). Otherwise ([force_dir = - false]), raise No_dir if [error] is [false]. - @since Neon-20140301 *) - - val dir: ?error:bool -> unit -> Filepath.Normalized.t - (** [dir ~error ()] returns the specific directory name, if - any. Otherwise, Frama-C halts on an user error if [error] or if the - behavior depends on [force_dir]. Default of [error] is [true]. - @raise No_dir if there is no share directory for this plug-in and [not - error] and [not force_dir]. *) - - val file: ?error:bool -> string -> Filepath.Normalized.t - (** [file basename] returns the complete filename of a file stored in [dir - ()]. If there is no such directory, Frama-C halts on an user error if - [error] or if the behavior depends on [force_dir]. Default of [error] is - [true]. - @raise No_dir if there is no share directory for this plug-in and [not - error] and [not force_dir]. *) + val set: Filepath.Normalized.t -> unit + val get: unit -> Filepath.Normalized.t + val is_set: unit -> bool - module Dir_name: Filepath - (** Option [-<short-name>-<specific-dir>]. *) + val get_dir: + ?mode:[`Create_path | `Normalize_only | `Must_exist ] -> + string -> + Filepath.Normalized.t + val get_file: + ?mode:[`Create_path | `Normalize_only | `Must_exist ] -> + string -> + Filepath.Normalized.t end (* ************************************************************************** *) diff --git a/src/kernel_services/plugin_entry_points/kernel.ml b/src/kernel_services/plugin_entry_points/kernel.ml index d437277a6da46c91e6edf8c6f882e1809331945f..41bde48cfc510df064794f528fca305d8401fee9 100644 --- a/src/kernel_services/plugin_entry_points/kernel.ml +++ b/src/kernel_services/plugin_entry_points/kernel.ml @@ -837,9 +837,9 @@ module Journal = struct let default = let dir = (* duplicate code from Plugin.Session *) - if Session.Dir_name.is_set () + if Session.is_set () then - (Session.Dir_name.get () :> string) + (Session.get () :> string) else try Sys.getenv "FRAMAC_SESSION" with Not_found -> "./.frama-c" diff --git a/src/kernel_services/plugin_entry_points/plugin.ml b/src/kernel_services/plugin_entry_points/plugin.ml index 4b7b4a2de3b925a0d3700d224e50f45bb70519a6..ecc78065fc36d43580326ef27ed77b83c880cf5d 100644 --- a/src/kernel_services/plugin_entry_points/plugin.ml +++ b/src/kernel_services/plugin_entry_points/plugin.ml @@ -299,13 +299,11 @@ struct (D: sig val dirs: unit -> string list val visible_ref: bool - val force_dir: bool end) = struct let is_visible = D.visible_ref - let force_dir = D.force_dir let is_kernel = is_kernel () (* the side effect must be applied right now *) let () = @@ -323,65 +321,95 @@ struct let file_kind = "" end) - exception No_dir - let mk_dir d = try Extlib.mkdir ~parents:true d 0o755; L.warning "creating %s directory `%s'" O.option_name d; d with Unix.Unix_error _ -> - L.warning "cannot create %s directory `%s'" O.option_name d; - raise No_dir - - let rec get_and_check_dirs error = function - | [] -> - raise No_dir - | d::l -> - if (try Sys.is_directory d with Sys_error _ -> false) then d - else - get_and_check_dirs error l - - let get_and_check_dirs ?(error=true) = function - | [] -> - if error then - L.abort "no %s directories to look into" O.option_name - else - raise No_dir - | (first::_) as l -> - try - get_and_check_dirs error l - with - | No_dir when error -> - L.abort "no %s directory for plug-in `%s' among %a" - O.option_name - P.name - Pretty_utils.(pp_list ~sep:",@ " Format.pp_print_string) l - | No_dir when force_dir -> - (* create the parent, if it does not exist *) - let p = Filename.dirname first in - if not (try Sys.is_directory p with Sys_error _ -> false) then - ignore (mk_dir p); - mk_dir first - - let dir ?error () = - (* get the specified dir if any *) - let d = if is_visible then (Dir_name.get () :> string) else empty_string in - let dirs = - if d = empty_string + L.abort "cannot create %s directory `%s'" O.option_name d + + let set filepath = Dir_name.set filepath + let get () = Dir_name.get () + let is_set () = Dir_name.is_set () + + let base_dirs () = + (* Get the specified dir if any. *) + let plugin_base_dir = + if is_visible + then Dir_name.get () + else Datatype.Filepath.dummy + in + if not (plugin_base_dir = Datatype.Filepath.dummy) + then [plugin_base_dir] + else begin + (* No specified dir: look for the default one. *) + let dirs = D.dirs () in + assert (dirs <> []); + if is_kernel then - (* no specified dir: look for the default one. *) - if is_kernel - then D.dirs () - else List.map (fun x -> x ^ "/" ^ plugin_subpath) (D.dirs ()) + List.map Datatype.Filepath.of_string dirs else - [d] - in - Datatype.Filepath.of_string (get_and_check_dirs ?error dirs) + List.map + (fun x -> Datatype.Filepath.of_string (x ^ "/" ^ plugin_subpath)) + dirs + end - let file ?error f = - let dir = dir ?error () in - Datatype.Filepath.concat dir ("/" ^ f) + let get_dir ?(mode=`Normalize_only) s = + match mode with + | `Must_exist -> + begin + let dir = + let exception Found of Datatype.Filepath.t in + try + List.fold_left + (fun dummy d -> + let name = Datatype.Filepath.concat d ("/" ^ s) in + if Sys.file_exists (name :> string) + then raise (Found name) + else dummy) + None + (base_dirs ()) + with Found d -> + Some d + in + match dir with + | None -> + L.abort "no directory %s exist in %s directories" s O.option_name + | Some d -> d + end + | _ -> + begin + let filepath = + match base_dirs () with + | [] -> assert false + | d :: _ -> Datatype.Filepath.concat d ("/" ^ s) + in + match mode with + | `Must_exist -> + (* Already taken care of. *) + assert false + | `Normalize_only -> + filepath + | `Create_path -> + ignore (mk_dir (filepath :> string)); + filepath + end + + let get_file ?(mode=`Normalize_only) s = + let s_dirname = Filename.dirname s in + let base_dir = get_dir ~mode s_dirname in + let s_basename = Filename.basename s in + let filepath = Datatype.Filepath.concat base_dir ("/" ^ s_basename) in + match mode with + | `Must_exist -> + if Sys.file_exists (filepath :> string) + then filepath + else L.abort "no file %s exist in %s directories" s O.option_name + | `Normalize_only -> + filepath + | `Create_path -> + filepath end @@ -396,7 +424,6 @@ struct (struct let dirs () = Fc_config.datadirs let visible_ref = !share_visible_ref - let force_dir = false end) module Session = @@ -413,11 +440,10 @@ struct try Sys.getenv "FRAMAC_SESSION" with Not_found -> "./.frama-c"] let visible_ref = !session_visible_ref - let force_dir = true end) let () = if is_kernel () - then Journal.get_session_file := (fun s -> Session.file ~error:false s) + then Journal.get_session_file := (fun s -> Session.get_file s) module Config = Make_specific_dir @@ -445,7 +471,6 @@ struct d ^ if vis then "/frama-c" else "/.frama-c" ] let visible_ref = !config_visible_ref - let force_dir = true end) let help = add_group "Getting Information" diff --git a/src/plugins/e-acsl/src/libraries/misc.ml b/src/plugins/e-acsl/src/libraries/misc.ml index 285438e7d87be09f19608712a09634902f61c0af..0f4d38ef3fb6f37bd2ab33dd37c1f0d1ff021063 100644 --- a/src/plugins/e-acsl/src/libraries/misc.ml +++ b/src/plugins/e-acsl/src/libraries/misc.ml @@ -30,7 +30,7 @@ open Cil_datatype let library_files () = List.map - (fun d -> Options.Share.file ~error:true d) + (fun d -> Options.Share.get_file ~mode:`Must_exist d) [ "e_acsl_gmp_api.h"; "e_acsl.h" ] diff --git a/src/plugins/e-acsl/src/main.ml b/src/plugins/e-acsl/src/main.ml index c8027aa8d6f690b468b5aae66a1e98e8e957fdfc..a7f26523d4c08bd8b4028b8522d8f3073ecb857c 100644 --- a/src/plugins/e-acsl/src/main.ml +++ b/src/plugins/e-acsl/src/main.ml @@ -38,7 +38,7 @@ let extended_ast_project: extended_project ref = ref To_be_extended let unmemoized_extend_ast () = let extend () = - let share = Options.Share.dir ~error:true () in + let share = Options.Share.get_dir ~mode:`Must_exist "." in Options.feedback ~level:3 "setting kernel options for E-ACSL."; Kernel.CppExtraArgs.add (Format.asprintf " -DE_ACSL_MACHDEP=%s -I%a/memory_model" diff --git a/src/plugins/gui/gtk_helper.ml b/src/plugins/gui/gtk_helper.ml index 298d75d184f3a4716f4ba7573be412659061ef06..9253046cb295846e25da7e910bda4095d3ccd40c 100644 --- a/src/plugins/gui/gtk_helper.ml +++ b/src/plugins/gui/gtk_helper.ml @@ -47,8 +47,7 @@ let framac_logo, framac_icon = module Configuration = struct include Cilconfig let configuration_file () = - try (Gui_parameters.Config.file ~error:false "frama-c-gui.config") - with Gui_parameters.Config.No_dir -> Datatype.Filepath.dummy + Gui_parameters.Config.get_file "frama-c-gui.config" let load () = loadConfiguration (configuration_file ()) let save () = saveConfiguration (configuration_file ()) let reset () = Extlib.safe_remove (configuration_file () :> string); diff --git a/src/plugins/wp/ProverErgo.ml b/src/plugins/wp/ProverErgo.ml index 9ad747a9afb3196f58a6a8712e520b6d7a873866..a1f4594ddba1101cda469be56dd43fe3d88e5875 100644 --- a/src/plugins/wp/ProverErgo.ml +++ b/src/plugins/wp/ProverErgo.ml @@ -165,7 +165,7 @@ class visitor fmt c = let df = D_file f in if not (List.mem df deps) then deps <- df :: deps - method add_shared f = self#add_dfile ((Wp_parameters.Share.file ~error:true f) :> string) + method add_shared f = self#add_dfile ((Wp_parameters.Share.get_file ~mode:`Must_exist f) :> string) method add_library f = self#add_dfile f method on_cluster c = deps <- (D_cluster c) :: deps diff --git a/src/plugins/wp/ProverWhy3.ml b/src/plugins/wp/ProverWhy3.ml index b4074ed1bb1b9f989a06f9e145794ec2aee52a6c..2b31bf272f2bded093f4c811297210f43fc01cdb 100644 --- a/src/plugins/wp/ProverWhy3.ml +++ b/src/plugins/wp/ProverWhy3.ml @@ -51,7 +51,7 @@ let get_why3_env = Env.memoize let main = Why3.Whyconf.get_main config in let ld = (WpContext.directory ()):: - ((Wp_parameters.Share.file "why3") :> string):: + ((Wp_parameters.Share.get_file "why3") :> string):: (Why3.Whyconf.loadpath main) in Why3.Env.create_env ld end @@ -786,7 +786,7 @@ class visitor (ctx:context) c = let copy_file source = if not (Datatype.Filepath.equal (Datatype.Filepath.of_string (Filename.dirname source)) - (Wp_parameters.Share.dir ())) + (Wp_parameters.Share.get_dir ".")) then let tgtdir = WpContext.directory () in let why3src = Filename.basename source in diff --git a/src/plugins/wp/driver.mll b/src/plugins/wp/driver.mll index d541988a96627f9bc479832c2b7ecf9422b6a758..1a13f28d9e6b5f17eb2ebc38f3ddfc6435aae216 100644 --- a/src/plugins/wp/driver.mll +++ b/src/plugins/wp/driver.mll @@ -501,8 +501,8 @@ and bal = parse let descr = String.concat "," drvs in let includes = let directories = - try [(Wp_parameters.Share.dir ~error:false () :> string)] - with Wp_parameters.Share.No_dir -> [] in + [(Wp_parameters.Share.get_dir "." :> string)] + in if Wp_parameters.has_dkey dkey then Wp_parameters.debug ~dkey "Included directories:%t" (fun fmt -> @@ -519,8 +519,8 @@ and bal = parse then Filepath.normalize file else LogicBuiltins.find_lib file) drivers in - let default = Wp_parameters.Share.file ~error:true "wp.driver" in - let feedback = Wp_parameters.Share.Dir_name.is_set () in + let default = Wp_parameters.Share.get_file ~mode:`Must_exist "wp.driver" in + let feedback = Wp_parameters.Share.is_set () in let ontty = if feedback then `Message else `Transient in load_file ~ontty (default :> string); List.iter load_file drivers diff --git a/src/plugins/wp/register.ml b/src/plugins/wp/register.ml index bc0cf0c9d05b4bc49359bbba300b655823f449bc..b6c45ae76c0d113fd33ed5378b7a1e197ae4280c 100644 --- a/src/plugins/wp/register.ml +++ b/src/plugins/wp/register.ml @@ -557,7 +557,7 @@ let spawn_wp_proofs_iter ~mode iter_on_goals = if mode.tactical || mode.provers<>[] then begin let server = ProverTask.server () in - ignore (Wp_parameters.Share.dir ()); (* To prevent further errors *) + ignore (Wp_parameters.Share.get_dir "."); (* To prevent further errors *) iter_on_goals (fun goal -> if mode.tactical diff --git a/src/plugins/wp/wp_parameters.ml b/src/plugins/wp/wp_parameters.ml index c1d7d6ad7193254c12a6a6f973fa8c5913f3a775..7d8a2e381c2f113d42356837e80079a93d62a117 100644 --- a/src/plugins/wp/wp_parameters.ml +++ b/src/plugins/wp/wp_parameters.ml @@ -1118,21 +1118,21 @@ let get_output_dir d = let default = Sys.getcwd () ^ "/.frama-c" let has_session () = - Session.Dir_name.is_set () || + Session.is_set () || ( Sys.file_exists default && Sys.is_directory default ) let get_session ~force () = if force then - Session.dir ~error:false () + Session.get_dir "." else - if Session.Dir_name.is_set () then - Session.Dir_name.get () + if Session.is_set () then + Session.get () else - Session.dir ~error:false () + Session.get_dir "." let get_session_dir ~force d = let base = get_session ~force () in - let path = Format.asprintf "%a/%s" Datatype.Filepath.pp_abs base d in + let path = Format.asprintf "%s/%s" (base :> string) d in if force then make_output_dir path ; path (* -------------------------------------------------------------------------- *)