(**************************************************************************) (* *) (* OCaml *) (* *) (* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) (* *) (* Copyright 2001 Institut National de Recherche en Informatique et *) (* en Automatique. *) (* *) (* All rights reserved. This file is distributed under the terms of *) (* the GNU Lesser General Public License version 2.1, with the *) (* special exception on linking described in the file LICENSE. *) (* *) (**************************************************************************) (** Representation of element names. *) let infix_chars = [ '|' ; '<' ; '>' ; '@' ; '^' ; '&' ; '+' ; '-' ; '*' ; '/' ; '$' ; '%' ; '=' ; ':' ; '~' ; '!' ; '.' ; '#' ; ] type t = string let strip_string s = let len = String.length s in let rec iter_first n = if n >= len then None else match s.[n] with ' ' | '\t' | '\n' | '\r' -> iter_first (n+1) | _ -> Some n in match iter_first 0 with None -> "" | Some first -> let rec iter_last n = if n <= first then None else match s.[n] with ' ' | '\t' | '\n' | '\r' -> iter_last (n-1) | _ -> Some n in match iter_last (len-1) with None -> String.sub s first 1 | Some last -> String.sub s first ((last-first)+1) let parens_if_infix name = match strip_string name with | "" -> "" | s when s.[0] = '*' || s.[String.length s - 1] = '*' -> "( " ^ s ^ " )" | s when List.mem s.[0] infix_chars -> "(" ^ s ^ ")" | "or" | "mod" | "land" | "lor" | "lxor" | "lsl" | "lsr" | "asr" -> "(" ^ name ^ ")" | name -> name ;; let cut name = match name with "" -> ("", "") | s -> let len = String.length s in match s.[len-1] with ')' -> ( let j = ref 0 in let buf = [|Buffer.create len ; Buffer.create len |] in for i = 0 to len - 1 do match s.[i] with '.' when !j = 0 -> if i < len - 1 then match s.[i+1] with '(' -> j := 1 | _ -> Buffer.add_char buf.(!j) '.' else Buffer.add_char buf.(!j) s.[i] | c -> Buffer.add_char buf.(!j) c done; (Buffer.contents buf.(0), Buffer.contents buf.(1)) ) | _ -> match List.rev (Str.split (Str.regexp_string ".") s) with [] -> ("", "") | h :: q -> (String.concat "." (List.rev q), h) let simple name = snd (cut name) let father name = fst (cut name) let concat n1 n2 = n1^"."^n2 let normalize_name name = let (p,s) = cut name in let len = String.length s in let s = if len >= 2 && s.[0] = '(' && s.[len - 1] = ')' then parens_if_infix (strip_string (String.sub s 1 (len - 2))) else s in match p with "" -> s | p -> concat p s ;; let head_and_tail n = try let pos = String.index n '.' in if pos > 0 then let h = String.sub n 0 pos in try ignore (String.index h '('); (n, "") with Not_found -> let len = String.length n in if pos >= (len - 1) then (h, "") else (h, String.sub n (pos + 1) (len - pos - 1)) else (n, "") with Not_found -> (n, "") let head n = fst (head_and_tail n) let depth name = try List.length (Str.split (Str.regexp "\\.") name) with _ -> 1 let prefix n1 n2 = (n1 <> n2) && (try let len1 = String.length n1 in ((String.sub n2 0 len1) = n1) && (n2.[len1] = '.') with _ -> false) let rec get_relative_raw n1 n2 = let (f1,s1) = head_and_tail n1 in let (f2,s2) = head_and_tail n2 in if f1 = f2 then if f2 = s2 || s2 = "" then s2 else if f1 = s1 || s1 = "" then s2 else get_relative_raw s1 s2 else n2 let get_relative n1 n2 = if prefix n1 n2 then let len1 = String.length n1 in try String.sub n2 (len1+1) ((String.length n2) - len1 - 1) with _ -> n2 else n2 let get_relative_opt n1 n2 = if n1 = "" then n2 else if prefix n1 n2 then let len1 = String.length n1 in try String.sub n2 (len1+1) ((String.length n2) - len1 - 1) with _ -> n2 else n2 let alias_unprefix ln s = if ln = "" then s else let p = ln ^ "__" in let n, k = String.(length p, length s) in if k > n && String.sub s 0 n = p then String.( capitalize_ascii @@ sub s n (k-n) ) else s let hide_given_modules l s = let rec iter = function [] -> s | h :: q -> let s2 = get_relative h s in if s = s2 then iter q else s2 in iter l let qualified name = String.contains name '.' let from_ident ident = Ident.name ident let from_path path = Path.name path let to_path n = match List.fold_left (fun acc_opt -> fun s -> match acc_opt with None -> Some (Path.Pident (Ident.create_local s)) | Some acc -> Some (Path.Pdot (acc, s))) None (Str.split (Str.regexp "\\.") n) with None -> raise (Failure "to_path") | Some p -> p let from_longident = Odoc_misc.string_of_longident module Map = Map.Make(String)