exception Malformed_key of string
exception Key_not_found of string
+exception Cyclic_definition of string
exception Type_error of string * string * string (* expected type, value, msg *)
exception Parse_error of string * int * int * string (* file, line, col, msg *)
exception Invalid_value of (string * string) * string (* key, value, descr *)
* - no sequences of '_' longer than 1 are permitted
* - no uppercase letter are permitted
*)
+(*
let valid_step_rex_raw = "[a-z0-9]+(_[a-z0-9]+)*"
let valid_key_rex_raw =
- sprintf "%s(\\.%s)*" valid_step_rex_raw valid_step_rex_raw
-let valid_key_rex = Pcre.regexp ("^" ^ valid_key_rex_raw ^ "$")
+ sprintf "^%s(\\.%s)*$" valid_step_rex_raw valid_step_rex_raw
+let valid_key_rex = Pcre.regexp valid_key_rex_raw
+let dot_rex = Pcre.regexp "\\."
+let spaces_rex = Pcre.regexp "\\s+"
+let heading_spaces_rex = Pcre.regexp "^\\s+"
+*)
+let valid_step_rex_raw = "[a-z0-9]+\\(_[a-z0-9]+\\)*"
+let valid_key_rex_raw =
+ sprintf "%s\(\\.%s\)*" valid_step_rex_raw valid_step_rex_raw
+let valid_key_rex = Str.regexp ("^" ^ valid_key_rex_raw ^ "$")
+let interpolated_key_rex = Str.regexp ("\\$(" ^ valid_key_rex_raw ^ ")")
+let dot_rex = Str.regexp "\\."
+let spaces_rex = Str.regexp "[ \t\n\r]+"
+let heading_spaces_rex = Str.regexp "^[ \t\n\r]+"
(* escapes for xml configuration file *)
let (escape, unescape) =
Netencoding.Html.decode ~in_enc ~out_enc ~entity_base:`Xml ())
let key_is_valid key =
- if not (Pcre.pmatch ~rex:valid_key_rex key) then
+(* if not (Pcre.pmatch ~rex:valid_key_rex key) then *)
+ if not (Str.string_match valid_key_rex key 0) then
raise (Malformed_key key)
let value_is_valid ~key ~value =
value_is_valid ~key ~value;
Hashtbl.replace registry key value
-let env_var_of_key =
- let dot_RE = Pcre.regexp "\\." in
- fun key ->
- Pcre.replace ~rex:dot_RE ~templ:"__" (String.uppercase key)
+let env_var_of_key key =
+(* Pcre.replace ~rex:dot_rex ~templ:"__" (String.uppercase key) *)
+ Str.global_replace dot_rex "__" (String.uppercase key)
let get key =
- key_is_valid key;
- let registry_value =
- try
- Some (Hashtbl.find registry key)
- with Not_found -> None
- in
- let env_value =
- try
- Some (Sys.getenv (env_var_of_key key))
- with Not_found -> None
+ let rec aux stack key =
+ key_is_valid key;
+ if List.mem key stack then begin
+ let msg = (String.concat " -> " (List.rev stack)) ^ " -> " ^ key in
+ raise (Cyclic_definition msg)
+ end;
+ let registry_value = (* internal value *)
+ try
+ Some (Hashtbl.find registry key)
+ with Not_found -> None
+ in
+ let env_value = (* environment value *)
+ try
+ Some (Sys.getenv (env_var_of_key key))
+ with Not_found -> None
+ in
+ let value = (* resulting value *)
+ match (registry_value, env_value) with
+ | Some reg, Some env -> env
+ | Some reg, None -> reg
+ | None, Some env -> env
+ | None, None -> raise (Key_not_found key)
+ in
+ interpolate (key :: stack) value
+ and interpolate stack value =
+ Str.global_substitute interpolated_key_rex
+ (fun s ->
+ let matched = Str.matched_string s in
+ (* "$(var)" -> "var" *)
+ let key = String.sub matched 2 (String.length matched - 3) in
+ aux stack key)
+ value
in
- match (registry_value, env_value) with
- | Some reg, Some env -> env
- | Some reg, None -> reg
- | None, Some env -> env
- | None, None -> raise (Key_not_found key)
+ aux [] key
let set = set' registry
let string_list_of_string s =
- (* trailing blanks are removed per default by Pcre.split *)
- Pcre.split ~pat:"\\s+" (Pcre.replace ~pat:"^\\s+" s)
+ (* trailing blanks are removed per default by split *)
+(* Pcre.split ~res:spaces_rex (Pcre.replace ~rex:heading_spaces_rex s) *)
+ Str.split spaces_rex (Str.global_replace heading_spaces_rex "" s)
let string_of_string_list l = String.concat " " l
let mk_get_set type_name (from_string: string -> 'a) (to_string: 'a -> string) =