123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170open!ImportmoduleLargeFile=Unix.LargeFileletgetenv_f~fvar=trySome(fvar)withNot_found_s_|Caml.Not_found->Noneletgetenv=getenv_f~f:Sys.getenvletunsafe_getenv=getenv_f~f:Unix.unsafe_getenvletgetenv_exn_f~f_str~fvar=matchfvarwith|Somex->x|None->Printf.failwithf"%s: environment variable %s is not set"f_strvar();;letgetenv_exn=getenv_exn_f~f_str:"Sys.getenv_exn"~f:getenvletunsafe_getenv_exn=getenv_exn_f~f_str:"Sys.unsafe_getenv_exn"~f:unsafe_getenvletstat_check_exnf?(follow_symlinks=true)path=letrecloop()=tryf(iffollow_symlinksthenLargeFile.statpathelseLargeFile.lstatpath)with|Unix.Unix_error(Unix.EINTR,_,_)->loop()|Unix.Unix_error((Unix.ENOENT|Unix.ENOTDIR),_,_)->falseinloop();;letstat_checkf?follow_symlinkspath=tryifstat_check_exnf?follow_symlinkspaththen`Yeselse`Nowith|Unix.Unix_error((Unix.EACCES|Unix.ELOOP),_,_)->`Unknown;;letfile_exists=stat_check(fun_->true)letfile_exists_exn=stat_check_exn(fun_->true)letis_directory=stat_check(funstat->stat.LargeFile.st_kind=Unix.S_DIR)letis_directory_exn=stat_check_exn(funstat->stat.LargeFile.st_kind=Unix.S_DIR)letis_file=stat_check(funstat->stat.LargeFile.st_kind=Unix.S_REG)letis_file_exn=stat_check_exn(funstat->stat.LargeFile.st_kind=Unix.S_REG)includestructopenCaml.Sysletargv=argvletexecutable_name=executable_nameletremove=removeletrename=renameletcommand=commandletchdir=chdirletgetcwd=getcwdletreaddir=readdirletinteractive=interactiveletos_type=os_typeletword_size=word_sizeletint_size=int_sizeletbig_endian=big_endianexceptionBreak=Breakletcatch_break=catch_breakletocaml_version=ocaml_versionendexceptionCommand_failed_with_statusofInt.t*String.t[@@derivingsexp]letcommand_exnstring=letstatus=commandstringinifstatus<>0thenraise(Command_failed_with_status(status,string));;letunix_quotex=ifnot(String.is_emptyx)&&String.for_allx~f:(function|'a'..'z'|'A'..'Z'|'0'..'9'|'_'|'-'|':'|'.'|'/'|','|'+'|'='|'%'|'@'->true|_->false)then(* Shell keywords, as output by [compgen -k] for bash, [man dash] for dash, and [PATH=
type -m '*' | grep reserved] for zsh, except for keywords that have special
characters like [[. Note that builtins don't matter because 'alias' and alias
behave the same, unlike 'if' and if. *)matchxwith|"if"|"then"|"else"|"elif"|"fi"|"case"|"esac"|"for"|"select"|"while"|"until"|"do"|"done"|"in"|"function"|"time"|"coproc"|"foreach"|"repeat"|"nocorrect"->Filename.quotex|_->xelseFilename.quotex;;letquote=matchCaml.Sys.os_typewith|"Unix"->unix_quote|_->Filename.quote;;letfold_dir~init~fdirectory=Array.fold(readdirdirectory)~f~initletls_dirdirectory=Array.to_list(readdirdirectory)(* This function takes six units to cause ocaml to call a different
function when executing bytecode:
http://caml.inria.fr/pub/docs/manual-ocaml/intfc.html#sec400
*)externalexecuting_bytecode:unit->unit->unit->unit->unit->unit->bool="executing_bytecode""not_executing_bytecode"[@@noalloc]letexecution_mode()=ifexecuting_bytecode()()()()()()then`Bytecodeelse`Native(* returns size, in bits, of an [int] type in C *)externalc_int_size:unit->int="c_int_size"[@@noalloc]lethome_directory()=matchgetenv"HOME"with|Somehome->home|None->(Unix.getpwuid(Unix.geteuid())).pw_direxternalopaque_identity:'a->'a="%opaque"modulePrivate=structletunix_quote=unix_quoteend[%%ifocaml_version<(4,09,0)]letoverride_argvargs=letlen=Array.lengthargsinassert(len<=Array.lengthSys.argv);Array.blit~src:args~src_pos:0~dst:Sys.argv~dst_pos:0~len;(Caml.Obj.truncate[@ocaml.alert"-deprecated"])(Obj.reprSys.argv)len;Arg.current:=0;;;[%%else]externalcaml_sys_modify_argv:stringarray->unit="caml_sys_modify_argv";;letoverride_argvnew_argv=caml_sys_modify_argvnew_argv;Arg.current:=0[%%endif]