mirror of
https://github.com/corda/corda.git
synced 2025-01-07 13:38:47 +00:00
9441de4c38
This release is used in conjunction with the linux-sgx-driver Intial release: https://github.com/01org/linux-sgx-driver commit-id: 0e865ce5e6b297a787bcdc12d98bada8174be6d7 Intel-id: 33399 Signed-off-by: Angie Chinchilla <angie.v.chinchilla@intel.com>
309 lines
11 KiB
OCaml
309 lines
11 KiB
OCaml
(*
|
|
* Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in
|
|
* the documentation and/or other materials provided with the
|
|
* distribution.
|
|
* * Neither the name of Intel Corporation nor the names of its
|
|
* contributors may be used to endorse or promote products derived
|
|
* from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
*)
|
|
|
|
open Printf
|
|
|
|
(* It contains some utility functions. *)
|
|
let failwithf fmt = kprintf failwith fmt;;
|
|
let splitwith chr = Str.split (Str.regexp_string (Char.escaped chr))
|
|
|
|
(* For compatibility with F#. *)
|
|
let (|>) a f = f a
|
|
|
|
(* Generate a list of sequent number.
|
|
* ----------------------------------
|
|
*
|
|
* mk_seq 1 0 -> []
|
|
* mk_seq 1 1 -> [1]
|
|
* mk_seq 1 5 -> [1; 2; 3; 4; 5]
|
|
*)
|
|
let rec mk_seq from_num to_num =
|
|
if from_num > to_num then []
|
|
else from_num :: mk_seq (from_num + 1) to_num
|
|
|
|
(* Return a list without duplicated elements. *)
|
|
let dedup_list lst =
|
|
let rec do_dedup acc rst =
|
|
match rst with
|
|
[] -> acc
|
|
| h::t -> if List.mem h acc then do_dedup acc t
|
|
else do_dedup (h :: acc) t
|
|
in do_dedup [] lst
|
|
|
|
(* Print the usage of this program. *)
|
|
let usage (progname: string) =
|
|
eprintf "usage: %s [options] <file> ...\n" progname;
|
|
eprintf "\n[options]\n\
|
|
--search-path <path> Specify the search path of EDL files\n\
|
|
--use-prefix Prefix untrusted proxy with Enclave name\n\
|
|
--header-only Only generate header files\n\
|
|
--untrusted Generate untrusted proxy and bridge\n\
|
|
--trusted Generate trusted proxy and bridge\n\
|
|
--untrusted-dir <dir> Specify the directory for saving untrusted code\n\
|
|
--trusted-dir <dir> Specify the directory for saving trusted code\n\
|
|
--help Print this help message\n";
|
|
eprintf "\n\
|
|
If neither `--untrusted' nor `--trusted' is specified, generate both.\n";
|
|
exit 1
|
|
|
|
|
|
(* Command line parsing facilities. *)
|
|
type edger8r_params = {
|
|
input_files : string list;
|
|
use_prefix : bool;
|
|
header_only : bool;
|
|
gen_untrusted : bool; (* User specified `--untrusted' *)
|
|
gen_trusted : bool; (* User specified `--trusted' *)
|
|
untrusted_dir : string; (* Directory to save untrusted code *)
|
|
trusted_dir : string; (* Directory to save trusted code *)
|
|
}
|
|
|
|
(* The search paths are recored in the array below.
|
|
* W/o extra search paths specified, edger8r searchs from current directory.
|
|
*)
|
|
let search_paths = ref [|"."|]
|
|
|
|
(* The path separator is usually ':' on Linux and ';' on Windows.
|
|
* Concerning that we might compile this code with OCaml on Windows,
|
|
* we'd better don't assume that ':' is always used.
|
|
*)
|
|
let path_separator : char =
|
|
match Sys.os_type with
|
|
"Win32" -> ';'
|
|
| _ -> ':' (* "Unix" or "Cygwin" *)
|
|
|
|
(* Parse the command line and return a record of `edger8r_params'. *)
|
|
let rec parse_cmdline (progname: string) (cmdargs: string list) =
|
|
let use_pref = ref false in
|
|
let hd_only = ref false in
|
|
let untrusted= ref false in
|
|
let trusted = ref false in
|
|
let u_dir = ref "." in
|
|
let t_dir = ref "." in
|
|
let files = ref [] in
|
|
|
|
let rec local_parser (args: string list) =
|
|
match args with
|
|
[] -> ()
|
|
| op :: ops ->
|
|
match String.lowercase op with
|
|
"--use-prefix" -> use_pref := true; local_parser ops
|
|
| "--header-only"-> hd_only := true; local_parser ops
|
|
| "--untrusted" -> untrusted := true; local_parser ops
|
|
| "--trusted" -> trusted := true; local_parser ops
|
|
| "--untrusted-dir" ->
|
|
(match ops with
|
|
[] -> usage progname
|
|
| x::xs -> u_dir := x; local_parser xs)
|
|
| "--trusted-dir" ->
|
|
(match ops with
|
|
[] -> usage progname
|
|
| x::xs -> t_dir := x; local_parser xs)
|
|
| "--help" -> usage progname
|
|
| "--search-path" ->
|
|
if ops = [] then usage progname
|
|
else
|
|
let search_path_str = List.hd ops in
|
|
let extra_paths = splitwith path_separator search_path_str in
|
|
let extra_path_arry = Array.of_list extra_paths in
|
|
search_paths := Array.append extra_path_arry !search_paths;
|
|
local_parser (List.tl ops)
|
|
| _ -> files := op :: !files; local_parser ops
|
|
in
|
|
local_parser cmdargs;
|
|
let opt =
|
|
{ input_files = List.rev !files; use_prefix = !use_pref;
|
|
header_only = !hd_only; gen_untrusted = true; gen_trusted = true;
|
|
untrusted_dir = !u_dir; trusted_dir = !t_dir;
|
|
}
|
|
in
|
|
if !untrusted || !trusted (* User specified '--untrusted' or '--trusted' *)
|
|
then { opt with gen_trusted = !trusted; gen_untrusted = !untrusted }
|
|
else opt
|
|
|
|
let separator_str : string = Filename.dir_sep
|
|
|
|
(* Search the file within given search pathes.
|
|
* -------------------------------------------
|
|
*
|
|
* The second parameter is read from the global variable `search_paths'.
|
|
*
|
|
* get_file_path "Util.fs" [|"."|] -> "./Ast.fs"
|
|
* get_file_path "Util.fs" [|"misc/dir"; "../Edger8r"|] -> "../Edger8r/Ast.fs"
|
|
* get_file_path "Util.fs" [|"misc/dir"; "another/dir"|] -> Not_found
|
|
*)
|
|
let get_file_path (fname: string) =
|
|
let get_full_name path =
|
|
if Filename.is_relative fname then path ^ separator_str ^ fname
|
|
else fname
|
|
in
|
|
let targets = Array.map get_full_name !search_paths in
|
|
let fn_list = Array.to_list targets in
|
|
try
|
|
List.find Sys.file_exists fn_list
|
|
with
|
|
Not_found -> failwithf "File not found within search paths: %s\n" fname
|
|
|
|
(* Get the short name of the given file name.
|
|
* ------------------------------------------
|
|
*
|
|
* get_short_name "Util.fs" -> "Util"
|
|
* get_short_name "./Util.fs" -> "Util"
|
|
* get_short_name "misc/Util.fs" -> "Util"
|
|
*)
|
|
let get_short_name (fname: string) =
|
|
let bn = Filename.basename fname in
|
|
try Filename.chop_extension bn
|
|
with Invalid_argument _ -> bn
|
|
|
|
(* Helper functions that are not contained in OCaml standard library *)
|
|
let isdigit = function '0' | '1' .. '9' -> true | _ -> false
|
|
let isalpha = function 'a' .. 'z' | 'A' .. 'Z' -> true | _ -> false
|
|
let isalnum c = isdigit c || isalpha c
|
|
|
|
let str_map f s =
|
|
let len = String.length s in
|
|
let res = String.create len in
|
|
for i = 0 to len - 1 do
|
|
String.set res i (f (String.get s i))
|
|
done;
|
|
res
|
|
|
|
let str_to_list s =
|
|
let rec iter i lst =
|
|
if i < 0 then lst else iter (i - 1) (s.[i] :: lst)
|
|
in
|
|
iter (String.length s - 1) []
|
|
|
|
let str_forall p s = List.for_all p (str_to_list s)
|
|
|
|
(* Compute a string that conforms to C identifier.
|
|
*
|
|
* to_c_identifier "this foo" => "this_foo"
|
|
* to_c_identifier "3this" => "_this"
|
|
*
|
|
* The algorithm is simple, filter invalid characters to `_'.
|
|
*)
|
|
let to_c_identifier (s: string) =
|
|
let convert_char ch =
|
|
if isalnum ch then ch else '_'
|
|
in
|
|
let first_ch =
|
|
let ch = s.[0] in
|
|
if isalnum ch then ch else '_'
|
|
in
|
|
let rest_str =
|
|
String.sub s 1 (String.length s - 1)
|
|
in
|
|
Char.escaped first_ch ^ str_map convert_char rest_str
|
|
|
|
|
|
(* Check whether given string is a valid C identifier.
|
|
*
|
|
* is_c_identifier "this foo" => false
|
|
* is_c_identifier "3this" => false
|
|
* is_c_identifier "_this" => true
|
|
*)
|
|
let is_c_identifier(s: string) =
|
|
let first_ch = s.[0] in
|
|
let rest_str = String.sub s 1 (String.length s - 1) in
|
|
if isalpha first_ch || first_ch = '_'
|
|
then str_forall (fun ch -> isalnum ch || ch = '_') rest_str
|
|
else false
|
|
|
|
(* ocamlyacc doesn't expose definitions in header section,
|
|
* as a quick work-around, we put them here.
|
|
*)
|
|
let trusted_headers : string list ref = ref []
|
|
let untrusted_headers: string list ref = ref []
|
|
|
|
(* Create directory specified by `d'. *)
|
|
let create_dir (d: string) =
|
|
let curr_dir = Unix.getcwd () in
|
|
|
|
(* `get_root_dir' will be called with the head element of a list of
|
|
* sub-directories starting from root directory.
|
|
* The list will look like -
|
|
* ["home", "guest", ...] on Linux, while
|
|
* ["c:\\", "Users", ...] on Windows.
|
|
*)
|
|
let get_root_dir (dirs: string list) =
|
|
match Sys.os_type with
|
|
"Win32" -> List.hd dirs
|
|
| _ -> Filename.dir_sep
|
|
in
|
|
(* If we have a directory list like ["c:", ...], change the first element
|
|
* to "c:\\". Due to the fact that:
|
|
* Sys.file_exists "c:" => false
|
|
* Sys.file_exists "c:\\" => true
|
|
*)
|
|
let normalize (ds: string list) =
|
|
if Sys.os_type <> "Win32" then ds
|
|
else
|
|
let d = List.hd ds in
|
|
if String.length d = 2 && d.[1] = ':'
|
|
then (d ^ Filename.dir_sep) :: List.tl ds
|
|
else ds
|
|
in
|
|
let dir_exist_p dir =
|
|
if Sys.file_exists dir then
|
|
let stats = Unix.stat dir in
|
|
match stats.Unix.st_kind with
|
|
| Unix.S_DIR -> true
|
|
(* No need handle S_LNK because 'stat' will follow link. *)
|
|
| _ -> false
|
|
else false
|
|
in
|
|
let __do_create_and_goto_dir dir =
|
|
(if dir_exist_p dir then () else Unix.mkdir dir 0o755);
|
|
Unix.chdir dir
|
|
in
|
|
let do_create_dir () =
|
|
let rec do_create_dir_recursively dirs =
|
|
match dirs with
|
|
[] -> ()
|
|
| x::xs ->
|
|
__do_create_and_goto_dir x; do_create_dir_recursively xs
|
|
in
|
|
(* After splitting, we will get a list of all sub-directories.
|
|
* "/home/guest/some/path" -> ["home", "guest", "some", "path"];
|
|
* "c:\Users\guest\some\path" -> ["c:", "Users", "guest", "some", "path"].
|
|
*)
|
|
let dirs = normalize (Str.split (Str.regexp separator_str) d) in
|
|
let start_dir = if Filename.is_relative d then curr_dir else get_root_dir dirs in
|
|
Unix.chdir start_dir;
|
|
(* In case of continuous dir_sep in path string, we filter out empty strings. *)
|
|
do_create_dir_recursively (List.filter (fun s -> s <> "") dirs);
|
|
Unix.chdir curr_dir;
|
|
in
|
|
try do_create_dir ()
|
|
with exn -> (eprintf "error: failed to create directory: `%s'\n" d; exit 1)
|