123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289(*
* BatPervasives - Additional functions
* Copyright (C) 1996 Xavier Leroy
* 2003 Nicolas Cannasse
* 2007 Zheng Li
* 2008 David Teller
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version,
* with the special exception on linking described in file LICENSE.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*)##V<5##openPervasives##V>=5##openStdlibopenBatEnumletinput_linesch=BatEnum.from(fun()->tryinput_linechwithEnd_of_file->raiseBatEnum.No_more_elements)letinput_charsch=BatEnum.from(fun()->tryinput_charchwithEnd_of_file->raiseBatEnum.No_more_elements)type'a_mut_list={hd:'a;mutabletl:'a_mut_list;}letinput_listch=let_empty=Obj.magic[]inletrecloopdst=letr={hd=input_linech;tl=_empty}indst.tl<-r;looprinletr={hd=Obj.magic();tl=_empty}intrylooprwithEnd_of_file->Obj.magicr.tlletbuf_len=8192letinput_allic=letrecloopacctotalbufofs=letn=inputicbufofs(buf_len-ofs)inifn=0thenletres=Bytes.createtotalinletpos=total-ofsinlet_=Bytes.blitbuf0resposofsinletcollposbuf=letnew_pos=pos-buf_leninBytes.blitbuf0resnew_posbuf_len;new_posinlet_=List.fold_leftcollposaccinBytes.unsafe_to_stringreselseletnew_ofs=ofs+ninletnew_total=total+ninifnew_ofs=buf_lenthenloop(buf::acc)new_total(Bytes.createbuf_len)0elseloopaccnew_totalbufnew_ofsinloop[]0(Bytes.createbuf_len)0letinput_file?(bin=false)fname=letch=(ifbinthenopen_in_binelseopen_in)fnameinletstr=input_allchinclose_inch;strletoutput_file~filename~text=letch=open_outfilenameinoutput_stringchtext;close_outchletprint_bool=function|true->print_string"true"|false->print_string"false"letprerr_bool=function|true->prerr_string"true"|false->prerr_string"false"letstring_of_charc=String.make1cletrecdumpr=ifObj.is_intrthenstring_of_int(Obj.magicr:int)else(* Block. *)letrecget_fieldsacc=function|0->acc|n->letn=n-1inget_fields(Obj.fieldrn::acc)ninletrecis_listr=ifObj.is_intrthenr=Obj.repr0(* [] *)elselets=Obj.sizerandt=Obj.tagrint=0&&s=2&&is_list(Obj.fieldr1)(* h :: t *)inletrecget_listr=ifObj.is_intrthen[]elseleth=Obj.fieldr0andt=get_list(Obj.fieldr1)inh::tinletopaquename=(* XXX In future, print the address of value 'r'. Not possible
* in pure OCaml at the moment. *)"<"^name^">"inlets=Obj.sizerandt=Obj.tagrin(* From the tag, determine the type of block. *)matchtwith|_whenis_listr->letfields=get_listrin"["^String.concat"; "(List.mapdumpfields)^"]"|0->letfields=get_fields[]sin"("^String.concat", "(List.mapdumpfields)^")"|xwhenx=Obj.lazy_tag->(* Note that [lazy_tag .. forward_tag] are < no_scan_tag. Not
* clear if very large constructed values could have the same
* tag. XXX *)opaque"lazy"|xwhenx=Obj.closure_tag->opaque"closure"|xwhenx=Obj.object_tag->letfields=get_fields[]sinlet_clasz,id,slots=matchfieldswith|h::h'::t->h,h',t|_->assertfalsein(* No information on decoding the class (first field). So just print
* out the ID and the slots. *)"Object #"^dumpid^" ("^String.concat", "(List.mapdumpslots)^")"|xwhenx=Obj.infix_tag->opaque"infix"|xwhenx=Obj.forward_tag->opaque"forward"|xwhenx<Obj.no_scan_tag->letfields=get_fields[]sin"Tag"^string_of_intt^" ("^String.concat", "(List.mapdumpfields)^")"|xwhenx=Obj.string_tag->"\""^String.escaped(Obj.magicr:string)^"\""|xwhenx=Obj.double_tag->string_of_float(Obj.magicr:float)|xwhenx=Obj.abstract_tag->opaque"abstract"|xwhenx=Obj.custom_tag->opaque"custom"##V<5##|xwhenx=Obj.final_tag->##V<5##opaque"final"|xwhenx=Obj.double_array_tag->BatIO.to_string(BatArray.printBatFloat.print)(Obj.magicr:floatarray)|_->opaque(Printf.sprintf"unknown: tag %d size %d"ts)letdumpv=dump(Obj.reprv)letprint_anyocv=BatIO.nwriteoc(dumpv)includeBatInnerPervasivesletinvisible_args=ref1(* the number or arguments to ignore at the beginning of Sys.argv,
usually because program-name is put in argv.(0) *)letargs()=lete=BatArray.enumSys.argvinBatEnum.drop!invisible_argse;eletexe=Array.getSys.argv0letargv=Sys.argv(** {6 I/O}*)letprint_guessocv=BatIO.nwriteoc(dumpv)letprerr_guessv=prerr_endline(dumpv)letstdin=BatIO.stdinletstdout=BatIO.stdoutletstderr=BatIO.stderrletstdnull=BatIO.stdnullletopen_out=BatFile.open_outletopen_out_binname=BatIO.output_channel~cleanup:true(open_out_binname)letopen_out_genmodepermname=BatIO.output_channel~cleanup:true(open_out_genmodepermname)letflush=BatIO.flushletflush_all=BatIO.flush_allletclose_all=BatIO.close_allletoutput_char=BatChar.printletoutput_string=BatString.printletoutputocbufposlen=ignore(BatIO.outputocbufposlen)letoutput_substringocbufposlen=ignore(BatIO.output_substringocbufposlen)letoutput_byte=BatIO.write_byteletoutput_binary_int=BatIO.write_i32letoutput_binary_floatoutv=BatIO.write_i64out(BatInt64.bits_of_floatv)letoutput_valueoutv=BatMarshal.outputoutvletclose_out=BatIO.close_outletclose_out_noerrout=tryBatIO.close_outoutwith_->()letopen_in=BatFile.open_inletopen_in_binname=BatIO.input_channel~cleanup:true(open_in_binname)letopen_in_genmodepermfilename=BatIO.input_channel~cleanup:true(open_in_genmodepermfilename)letwrap_inner_iofa=tryfawithBatIO.No_more_input->raiseEnd_of_fileletinput_char=wrap_inner_ioBatIO.readletinput_line=wrap_inner_ioBatIO.read_lineletinput=wrap_inner_ioBatIO.inputletreally_inputinpbufposlen=wrap_inner_ioignore(BatIO.really_inputinpbufposlen)letinput_byte=wrap_inner_ioBatIO.read_byteletinput_binary_int=wrap_inner_ioBatIO.read_i32letinput_binary_floatinp=wrap_inner_ioBatInt64.float_of_bits(BatIO.read_i64inp)letclose_in=BatIO.close_inletclose_in_noerrinp=tryBatIO.close_ininpwith_->()letinput_value=BatMarshal.inputletprint_allinp=BatIO.copyinpBatIO.stdoutletprerr_allinp=BatIO.copyinpBatIO.stderrincludeBatList.Infix(**{6 Importing BatEnum}*)letforeachef=iterfeletexists=existsletfor_all=for_allletfold=foldletreduce=reduceletfind=findletpeek=peekletpush=pushletjunk=junkletmap=mapletfilter=filterletfilter_map=filter_mapletconcat=concatletprint=printletget=getletiter=iterletscanl=scanlincludeInfix(** {6 Operators}*)letundefined?(message="Undefined")_=failwithmessage(*$T undefined
ignore (Obj.magic (undefined ~message:"")); true
try ignore (undefined ~message:"FooBar" ()); false with Failure "FooBar" -> true
*)letverifyxex=ifxthen()elseraiseexletverify_argxs=ifxthen()elseinvalid_args(** {6 Clean-up}*)let_=at_exitclose_all;(*Called second*)at_exitflush_all(*Called first*)