123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292(**************************************************************************)(* *)(* OCaml *)(* *)(* Xavier Leroy and Damien Doligez, INRIA Rocquencourt *)(* *)(* Copyright 1996 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. *)(* *)(**************************************************************************)letgeneric_quotequotequotes=letl=String.lengthsinletb=Buffer.create(l+20)inBuffer.add_charb'\'';fori=0tol-1doifs.[i]='\''thenBuffer.add_stringbquotequoteelseBuffer.add_charbs.[i]done;Buffer.add_charb'\'';Buffer.contentsb(* This function implements the Open Group specification found here:
[[1]] http://pubs.opengroup.org/onlinepubs/9699919799/utilities/basename.html
In step 1 of [[1]], we choose to return "." for empty input.
(for compatibility with previous versions of OCaml)
In step 2, we choose to process "//" normally.
Step 6 is not implemented: we consider that the [suffix] operand is
always absent. Suffixes are handled by [chop_suffix] and [chop_extension].
*)letgeneric_basenameis_dir_sepcurrent_dir_namename=letrecfind_endn=ifn<0thenString.subname01elseifis_dir_sepnamenthenfind_end(n-1)elsefind_begn(n+1)andfind_begnp=ifn<0thenString.subname0pelseifis_dir_sepnamenthenString.subname(n+1)(p-n-1)elsefind_beg(n-1)pinifname=""thencurrent_dir_nameelsefind_end(String.lengthname-1)(* This function implements the Open Group specification found here:
[[2]] http://pubs.opengroup.org/onlinepubs/9699919799/utilities/dirname.html
In step 6 of [[2]], we choose to process "//" normally.
*)letgeneric_dirnameis_dir_sepcurrent_dir_namename=letrectrailing_sepn=ifn<0thenString.subname01elseifis_dir_sepnamenthentrailing_sep(n-1)elsebasenandbasen=ifn<0thencurrent_dir_nameelseifis_dir_sepnamenthenintermediate_sepnelsebase(n-1)andintermediate_sepn=ifn<0thenString.subname01elseifis_dir_sepnamenthenintermediate_sep(n-1)elseString.subname0(n+1)inifname=""thencurrent_dir_nameelsetrailing_sep(String.lengthname-1)moduleUnix=structletcurrent_dir_name="."letparent_dir_name=".."letdir_sep="/"letis_dir_sepsi=s.[i]='/'letis_relativen=String.lengthn<1||n.[0]<>'/'letis_implicitn=is_relativen&&(String.lengthn<2||String.subn02<>"./")&&(String.lengthn<3||String.subn03<>"../")letcheck_suffixnamesuff=String.lengthname>=String.lengthsuff&&String.subname(String.lengthname-String.lengthsuff)(String.lengthsuff)=suffletchop_suffix_opt~suffixfilename=letlen_s=String.lengthsuffixandlen_f=String.lengthfilenameiniflen_f>=len_sthenletr=String.subfilename(len_f-len_s)len_sinifr=suffixthenSome(String.subfilename0(len_f-len_s))elseNoneelseNonelettemp_dir_name=trySys.getenv"TMPDIR"withNot_found->"/tmp"letquote=generic_quote"'\\''"letbasename=generic_basenameis_dir_sepcurrent_dir_nameletdirname=generic_dirnameis_dir_sepcurrent_dir_nameendmoduleWin32=structletcurrent_dir_name="."letparent_dir_name=".."letdir_sep="\\"letis_dir_sepsi=letc=s.[i]inc='/'||c='\\'||c=':'letis_relativen=(String.lengthn<1||n.[0]<>'/')&&(String.lengthn<1||n.[0]<>'\\')&&(String.lengthn<2||n.[1]<>':')letis_implicitn=is_relativen&&(String.lengthn<2||String.subn02<>"./")&&(String.lengthn<2||String.subn02<>".\\")&&(String.lengthn<3||String.subn03<>"../")&&(String.lengthn<3||String.subn03<>"..\\")letcheck_suffixnamesuff=String.lengthname>=String.lengthsuff&&(lets=String.subname(String.lengthname-String.lengthsuff)(String.lengthsuff)inString.lowercase_asciis=String.lowercase_asciisuff)letchop_suffix_opt~suffixfilename=letlen_s=String.lengthsuffixandlen_f=String.lengthfilenameiniflen_f>=len_sthenletr=String.subfilename(len_f-len_s)len_sinifString.lowercase_asciir=String.lowercase_asciisuffixthenSome(String.subfilename0(len_f-len_s))elseNoneelseNonelettemp_dir_name=trySys.getenv"TEMP"withNot_found->"."letquotes=letl=String.lengthsinletb=Buffer.create(l+20)inBuffer.add_charb'\"';letrecloopi=ifi=lthenBuffer.add_charb'\"'elsematchs.[i]with|'\"'->loop_bs0i;|'\\'->loop_bs0i;|c->Buffer.add_charbc;loop(i+1);andloop_bsni=ifi=lthenbeginBuffer.add_charb'\"';add_bsn;endelsebeginmatchs.[i]with|'\"'->add_bs(2*n+1);Buffer.add_charb'\"';loop(i+1);|'\\'->loop_bs(n+1)(i+1);|_->add_bsn;loopiendandadd_bsn=for_j=1tondoBuffer.add_charb'\\';doneinloop0;Buffer.contentsblethas_drives=letis_letter=function|'A'..'Z'|'a'..'z'->true|_->falseinString.lengths>=2&&is_letters.[0]&&s.[1]=':'letdrive_and_paths=ifhas_drivesthen(String.subs02,String.subs2(String.lengths-2))else("",s)letdirnames=let(drive,path)=drive_and_pathsinletdir=generic_dirnameis_dir_sepcurrent_dir_namepathindrive^dirletbasenames=let(_drive,path)=drive_and_pathsingeneric_basenameis_dir_sepcurrent_dir_namepathendmoduleCygwin=structletcurrent_dir_name="."letparent_dir_name=".."letdir_sep="/"letis_dir_sep=Win32.is_dir_sepletis_relative=Win32.is_relativeletis_implicit=Win32.is_implicitletcheck_suffix=Win32.check_suffixletchop_suffix_opt=Win32.chop_suffix_optlettemp_dir_name=Unix.temp_dir_nameletquote=Unix.quoteletbasename=generic_basenameis_dir_sepcurrent_dir_nameletdirname=generic_dirnameis_dir_sepcurrent_dir_nameendlet(current_dir_name,parent_dir_name,dir_sep,is_dir_sep,is_relative,is_implicit,check_suffix,chop_suffix_opt,temp_dir_name,quote,basename,dirname)=matchSys.os_typewith|"Win32"->(Win32.current_dir_name,Win32.parent_dir_name,Win32.dir_sep,Win32.is_dir_sep,Win32.is_relative,Win32.is_implicit,Win32.check_suffix,Win32.chop_suffix_opt,Win32.temp_dir_name,Win32.quote,Win32.basename,Win32.dirname)|"Cygwin"->(Cygwin.current_dir_name,Cygwin.parent_dir_name,Cygwin.dir_sep,Cygwin.is_dir_sep,Cygwin.is_relative,Cygwin.is_implicit,Cygwin.check_suffix,Cygwin.chop_suffix_opt,Cygwin.temp_dir_name,Cygwin.quote,Cygwin.basename,Cygwin.dirname)|_->(* normally "Unix" *)(Unix.current_dir_name,Unix.parent_dir_name,Unix.dir_sep,Unix.is_dir_sep,Unix.is_relative,Unix.is_implicit,Unix.check_suffix,Unix.chop_suffix_opt,Unix.temp_dir_name,Unix.quote,Unix.basename,Unix.dirname)letconcatdirnamefilename=letl=String.lengthdirnameinifl=0||is_dir_sepdirname(l-1)thendirname^filenameelsedirname^dir_sep^filenameletchop_suffixnamesuff=letn=String.lengthname-String.lengthsuffinifn<0theninvalid_arg"Filename.chop_suffix"elseString.subname0nletextension_lenname=letrecchecki0i=ifi<0||is_dir_sepnameithen0elseifname.[i]='.'thenchecki0(i-1)elseString.lengthname-i0inletrecsearch_doti=ifi<0||is_dir_sepnameithen0elseifname.[i]='.'thenchecki(i-1)elsesearch_dot(i-1)insearch_dot(String.lengthname-1)letextensionname=letl=extension_lennameinifl=0then""elseString.subname(String.lengthname-l)lletchop_extensionname=letl=extension_lennameinifl=0theninvalid_arg"Filename.chop_extension"elseString.subname0(String.lengthname-l)letremove_extensionname=letl=extension_lennameinifl=0thennameelseString.subname0(String.lengthname-l)externalopen_desc:string->open_flaglist->int->int="caml_sys_open"externalclose_desc:int->unit="caml_sys_close"letprng=lazy(Random.State.make_self_init())lettemp_file_nametemp_dirprefixsuffix=letrnd=(Random.State.bits(Lazy.forceprng))land0xFFFFFFinconcattemp_dir(Printf.sprintf"%s%06x%s"prefixrndsuffix)letcurrent_temp_dir_name=reftemp_dir_nameletset_temp_dir_names=current_temp_dir_name:=sletget_temp_dir_name()=!current_temp_dir_namelettemp_file?(temp_dir=!current_temp_dir_name)prefixsuffix=letrectry_namecounter=letname=temp_file_nametemp_dirprefixsuffixintryclose_desc(open_descname[Open_wronly;Open_creat;Open_excl]0o600);namewithSys_error_ase->ifcounter>=1000thenraiseeelsetry_name(counter+1)intry_name0letopen_temp_file?(mode=[Open_text])?(perms=0o600)?(temp_dir=!current_temp_dir_name)prefixsuffix=letrectry_namecounter=letname=temp_file_nametemp_dirprefixsuffixintry(name,open_out_gen(Open_wronly::Open_creat::Open_excl::mode)permsname)withSys_error_ase->ifcounter>=1000thenraiseeelsetry_name(counter+1)intry_name0