123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140open!Importopen!Std_internaltypet=string[@@derivingbin_io,compare,sexp]includestructopenCaml.Filenameletcheck_suffix=check_suffixletchop_extension=chop_extensionletchop_suffix=chop_suffixletcurrent_dir_name=current_dir_nameletis_implicit=is_implicitletis_relative=is_relativeletparent_dir_name=parent_dir_nameletdir_sep=dir_sepletquote=quotelettemp_dir_name=get_temp_dir_name()endletis_absolutep=not(is_relativep)letconcatp1p2=ifString.is_emptyp1thenfailwithf"Filename.concat called with an empty string as its first argument (second \
argument: %s)"p2();letreccollapse_trailings=matchString.rsplit2s~on:'/'with|Some("",("."|""))->""|Some(s,("."|""))->collapse_trailings|None|Some_->sinletreccollapse_leadings=matchString.lsplit2s~on:'/'with|Some(("."|""),s)->collapse_leadings|Some_|None->sincollapse_trailingp1^"/"^collapse_leadingp2;;(* Finds the largest index i in [s] that is less than [from] and for which
[f s.[i]]
returns true. Then it returns [i+1]. Raises an exception if [from] isn't a
valid index
in [s]. *)letstring_rexistss~f~from:n=letrecloopn=ifn=0thenNoneelseiffs.[n-1]thenSomenelseloop(n-1)inloopn;;letskip_end_slashess~from=matchstring_rexistss~from~f:(func->c<>'/')with|Somev->`Ends_atv|None->`All_slashes;;(*
Fix for #0004549. (in the inria bug tracker)
*)letsplit=function|""->".","."|s->(matchskip_end_slashess~from:(String.lengths)with|`All_slashes->"/","/"|`Ends_atbasename_end->(matchstring_rexistss~f:(func->c='/')~from:basename_endwith|None->".",String.sub~pos:0~len:basename_ends|Somebasename_start->letbasename=String.subs~pos:basename_start~len:(basename_end-basename_start)inletdirname=matchskip_end_slashess~from:basename_startwith|`All_slashes->"/"|`Ends_atdirname_end->String.sub~pos:0~len:dirname_endsindirname,basename));;(*
http://www.opengroup.org/onlinepubs/9699919799/utilities/basename.html
http://www.opengroup.org/onlinepubs/9699919799/utilities/dirname.html
*)letbasenamepath=snd(splitpath)letdirnamepath=fst(splitpath)(* [max_pathname_component_size] comes from getconf _POSIX_NAME_MAX / *)letmax_pathname_component_size=255letis_posix_pathname_components=letmoduleS=Stringins<>"."&&s<>".."&&0<S.lengths&&S.lengths<=max_pathname_component_size&¬(S.containss'/')&¬(S.containss'\000');;letroot="/"letsplit_extensionfn=letdir,fn=matchString.rsplit2~on:'/'fnwith|None->None,fn|Some(path,fn)->Somepath,fninletfn,ext=matchString.rsplit2~on:'.'fnwith|None->fn,None|Some(base_fn,ext)->base_fn,Someextinletfn=matchdirwith|None->fn|Somedir->dir^"/"^fninfn,ext;;letpartsfilename=letrecloopaccfilename=matchsplitfilenamewith|("."asbase),"."->base::acc|("/"asbase),"/"->base::acc|rest,dir->loop(dir::acc)restinloop[]filename;;letof_parts=function|[]->failwith"Filename.of_parts: empty parts list"|root::rest->List.foldrest~init:root~f:Caml.Filename.concat;;