1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231(* Js_of_ocaml compiler
* http://www.ocsigen.org/js_of_ocaml/
*
* This program 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, with linking exception;
* either version 2.1 of the License, or (at your option) any later version.
*
* This program 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 program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*)modulePoly=structexternal(<):'a->'a->bool="%lessthan"external(<=):'a->'a->bool="%lessequal"external(<>):'a->'a->bool="%notequal"external(=):'a->'a->bool="%equal"external(>):'a->'a->bool="%greaterthan"external(>=):'a->'a->bool="%greaterequal"externalcompare:'a->'a->int="%compare"externalequal:'a->'a->bool="%equal"endmoduleInt_replace_polymorphic_compare=structlet(<)(x:int)y=x<ylet(<=)(x:int)y=x<=ylet(<>)(x:int)y=x<>ylet(=)(x:int)y=x=ylet(>)(x:int)y=x>ylet(>=)(x:int)y=x>=yletcompare(x:int)y=comparexyletequal(x:int)y=x=yletmax(x:int)y=ifx>=ythenxelseyletmin(x:int)y=ifx<=ythenxelseyendletphys_equal=(==)let(==)=`use_phys_equallet(!=)=`use_phys_equalincludeInt_replace_polymorphic_compareletquiet=reffalseletwerror=reffalseletwarnings=ref0letwarnfmt=Format.ksprintf(funs->incrwarnings;ifnot!quietthenFormat.eprintf"%s%!"s)fmtletfail=reftrueletfailwith_fmt=Printf.ksprintf(funs->if!failthenfailwithselseFormat.eprintf"%s@."s)fmtletraise_exn=if!failthenraiseexnelseFormat.eprintf"%s@."(Printexc.to_stringexn)letint_num_bits=Sys.int_sizemoduleList=structincludeListLabelsletrecequal~eqab=matcha,bwith|[],[]->true|x::xs,y::ys->eqxy&&equal~eqxsys|[],_::_|_::_,[]->falseletrecfind_map~f=function|[]->None|x::l->(matchfxwith|Some_asresult->result|None->find_map~fl)letrecfind_map_value~f~default=function|[]->default|x::l->(matchfxwith|Someresult->result|None->find_map_value~f~defaultl)letrecrev_append_map~flacc=matchlwith|[]->acc|x::xs->rev_append_map~fxs(fx::acc)letslow_mapl~f=rev(rev_map~fl)letmax_non_tailcall=matchSys.backend_typewith|Sys.Native|Sys.Bytecode->1_000|Sys.Other_->50letreccount_map~flctr=matchlwith|[]->[]|[x1]->letf1=fx1in[f1]|[x1;x2]->letf1=fx1inletf2=fx2in[f1;f2]|[x1;x2;x3]->letf1=fx1inletf2=fx2inletf3=fx3in[f1;f2;f3]|[x1;x2;x3;x4]->letf1=fx1inletf2=fx2inletf3=fx3inletf4=fx4in[f1;f2;f3;f4]|x1::x2::x3::x4::x5::tl->letf1=fx1inletf2=fx2inletf3=fx3inletf4=fx4inletf5=fx5inf1::f2::f3::f4::f5::(ifctr>max_non_tailcallthenslow_map~ftlelsecount_map~ftl(ctr+1))letmapl~f=count_map~fl0letrectake'accnl=ifn=0thenacc,lelsematchlwith|[]->acc,[]|x::xs->take'(x::acc)(predn)xslettakenl=letx,xs=take'[]nlinrevx,xsletreclast=function|[]->None|[x]->Somex|_::xs->lastxsletsort_uniq~comparel=letl=List.sortcomparelinmatchlwith|([]|[_])asl->l|x::xs->letrecloopprev=function|[]->[prev]|x::restwhencomparexprev=0->loopprevrest|x::rest->prev::loopxrestinloopxxsletis_empty=function|[]->true|_->falseletpartition_mapt~f=letreclooptfstsnd=matchtwith|[]->revfst,revsnd|x::t->(matchfxwith|`Fsty->loopt(y::fst)snd|`Sndy->looptfst(y::snd))inloopt[][]lettail_appendl1l2=rev_append(revl1)l2letreccount_appendl1l2count=matchl2with|[]->l1|_->(matchl1with|[]->l2|[x1]->x1::l2|[x1;x2]->x1::x2::l2|[x1;x2;x3]->x1::x2::x3::l2|[x1;x2;x3;x4]->x1::x2::x3::x4::l2|x1::x2::x3::x4::x5::tl->x1::x2::x3::x4::x5::(ifcount>max_non_tailcallthentail_appendtll2elsecount_appendtll2(count+1)))letappendl1l2=count_appendl1l20letgroupl~f=letrecloop(l:'alist)(this_group:'alist)(acc:'alistlist):'alistlist=matchlwith|[]->List.rev(List.revthis_group::acc)|x::xs->letpred=List.hdthis_groupiniffxpredthenloopxs(x::this_group)accelseloopxs[x](List.revthis_group::acc)inmatchlwith|[]->[]|x::xs->loopxs[x][]letconcat_map~fl=letrecauxfacc=function|[]->revacc|x::l->letxs=fxinauxf(rev_appendxsacc)linauxf[]lletsplit_lastxs=letrecauxacc=function|[]->None|[x]->Some(revacc,x)|x::xs->aux(x::acc)xsinaux[]xs(* like [List.map] except that it calls the function with
an additional argument to indicate whether we're mapping
over the last element of the list *)letrecmap_last~fl=matchlwith|[]->assertfalse|[x]->[ftruex]|x::xs->ffalsex::map_last~fxs(* like [List.iter] except that it calls the function with
an additional argument to indicate whether we're iterating
over the last element of the list *)letreciter_last~fl=matchlwith|[]->()|[a]->ftruea|a::l->ffalsea;iter_last~flendlet(@)=List.appendmoduleNativeint=structincludeNativeintexternalequal:nativeint->nativeint->bool="%equal"endmoduleInt32=structincludeInt32external(<):int32->int32->bool="%lessthan"external(<=):int32->int32->bool="%lessequal"external(<>):int32->int32->bool="%notequal"external(=):int32->int32->bool="%equal"external(>):int32->int32->bool="%greaterthan"external(>=):int32->int32->bool="%greaterequal"externalcompare:int32->int32->int="%compare"externalequal:int32->int32->bool="%equal"letwarn_overflowname~to_dec~to_hexii32=warn"Warning: integer overflow: %s 0x%s (%s) truncated to 0x%lx (%ld); the generated \
code might be incorrect.@."name(to_hexi)(to_deci)i32i32letconvert_warning_on_overflowname~to_int32~of_int32~equal~to_dec~to_hexx=leti32=to_int32xinletx'=of_int32i32inifnot(equalx'x)thenwarn_overflowname~to_dec~to_hexxi32;i32letof_nativeint_warning_on_overflown=convert_warning_on_overflow"native integer"~to_int32:Nativeint.to_int32~of_int32:Nativeint.of_int32~equal:Nativeint.equal~to_dec:(Printf.sprintf"%nd")~to_hex:(Printf.sprintf"%nx")nendmoduleOption=structletmap~fx=matchxwith|None->None|Somev->Some(fv)letto_list=function|None->[]|Somex->[x]letbind~fx=matchxwith|None->None|Somev->fvletiter~fx=matchxwith|None->()|Somev->fvletfilter~fx=matchxwith|None->None|Somev->iffvthenSomevelseNoneletcomparecompare_eltab=matcha,bwith|None,None->0|None,Some_->-1|Some_,None->1|Somea,Someb->compare_eltabletequalequal_eltab=matcha,bwith|None,None->true|Somea,Someb->equal_eltab|Some_,None|None,Some_->falseletis_none=function|None->true|Some_->falseletis_some=function|None->false|Some_->trueletvalue~default=function|None->default|Somes->sendmoduleInt64=structincludeInt64letequal(a:int64)(b:int64)=Poly.(a=b)endmoduleFloat=structtypet=floatletequal(_:float)(_:float)=`Use_ieee_equal_or_bitwise_equalletieee_equal(a:float)(b:float)=Poly.equalabletbitwise_equal(a:float)(b:float)=Int64.equal(Int64.bits_of_floata)(Int64.bits_of_floatb)(* Re-defined here to stay compatible with OCaml 4.02 *)externalclassify_float:float->fpclass="caml_classify_float"external(<):t->t->bool="%lessthan"external(<=):t->t->bool="%lessequal"external(<>):t->t->bool="%notequal"external(=):t->t->bool="%equal"external(>):t->t->bool="%greaterthan"external(>=):t->t->bool="%greaterequal"endmoduleBool=structexternal(<>):bool->bool->bool="%notequal"external(=):bool->bool->bool="%equal"external(>):bool->bool->bool="%greaterthan"externalequal:bool->bool->bool="%equal"endmoduleChar=structincludeCharexternal(<):char->char->bool="%lessthan"external(<=):char->char->bool="%lessequal"external(<>):char->char->bool="%notequal"external(=):char->char->bool="%equal"external(>):char->char->bool="%greaterthan"external(>=):char->char->bool="%greaterequal"externalcompare:char->char->int="%compare"externalequal:char->char->bool="%equal"letis_alpha=function|'a'..'z'|'A'..'Z'->true|_->falseletis_num=function|'0'..'9'->true|_->falseletlowercase_asciic=matchcwith|'A'..'Z'asc->Char.unsafe_chr(Char.codec+32)|_->cletuppercase_asciic=matchcwith|'a'..'z'asc->Char.unsafe_chr(Char.codec-32)|_->cendmoduleUchar=structincludeUcharmoduleUtf_decode:sigtypeutf_decode[@@immediate](** The type for UTF decode results. Values of this type represent
the result of a Unicode Transformation Format decoding attempt. *)valutf_decode_is_valid:utf_decode->bool(** [utf_decode_is_valid d] is [true] if and only if [d] holds a valid
decode. *)valutf_decode_uchar:utf_decode->t(** [utf_decode_uchar d] is the Unicode character decoded by [d] if
[utf_decode_is_valid d] is [true] and {!Uchar.rep} otherwise. *)valutf_decode_length:utf_decode->int(** [utf_decode_length d] is the number of elements from the source
that were consumed by the decode [d]. This is always strictly
positive and smaller or equal to [4]. The kind of source elements
depends on the actual decoder; for the decoders of the standard
library this function always returns a length in bytes. *)valutf_decode:int->t->utf_decode(** [utf_decode n u] is a valid UTF decode for [u] that consumed [n]
elements from the source for decoding. [n] must be positive and
smaller or equal to [4] (this is not checked by the module). *)valutf_decode_invalid:int->utf_decode(** [utf_decode_invalid n] is an invalid UTF decode that consumed [n]
elements from the source to error. [n] must be positive and
smaller or equal to [4] (this is not checked by the module). The
resulting decode has {!rep} as the decoded Unicode character. *)valutf_8_byte_length:t->int(** [utf_8_byte_length u] is the number of bytes needed to encode
[u] in UTF-8. *)valutf_16_byte_length:t->int(** [utf_16_byte_length u] is the number of bytes needed to encode
[u] in UTF-16. *)end=struct(* UTF codecs tools *)typeutf_decode=int(* This is an int [0xDUUUUUU] decomposed as follows:
- [D] is four bits for decode information, the highest bit is set if the
decode is valid. The three lower bits indicate the number of elements
from the source that were consumed by the decode.
- [UUUUUU] is the decoded Unicode character or the Unicode replacement
character U+FFFD if for invalid decodes. *)letrep=0xFFFDletvalid_bit=27letdecode_bits=24let[@inline]utf_decode_is_validd=dlsrvalid_bit=1let[@inline]utf_decode_lengthd=(dlsrdecode_bits)land0b111let[@inline]utf_decode_uchard=unsafe_of_int(dland0xFFFFFF)let[@inline]utf_decodenu=((8lorn)lsldecode_bits)lorto_intulet[@inline]utf_decode_invalidn=(nlsldecode_bits)lorrepletutf_8_byte_lengthu=matchto_intuwith|uwhenu<0->assertfalse|uwhenu<=0x007F->1|uwhenu<=0x07FF->2|uwhenu<=0xFFFF->3|uwhenu<=0x10FFFF->4|_->assertfalseletutf_16_byte_lengthu=matchto_intuwith|uwhenu<0->assertfalse|uwhenu<=0xFFFF->2|uwhenu<=0x10FFFF->4|_->assertfalseendincludeUtf_decodeendmoduleBuffer=structincludeBufferletarray_conv=Array.init16(funi->"0123456789abcdef".[i])letadd_char_hexb(c:Char.t)=letc=Char.codecinBuffer.add_charb(Array.unsafe_getarray_conv(clsr4));Buffer.add_charb(Array.unsafe_getarray_conv(cland0xf))endmoduleBytes=structincludeBytesLabelsletsub_stringb~pos:ofs~len=unsafe_to_string(Bytes.subbofslen)letfold_left~f~initb=letr=refinitinfori=0tolengthb-1dor:=f!r(unsafe_getbi)done;!rletfold_right~fb~init=letr=refinitinfori=lengthb-1downto0dor:=f(unsafe_getbi)!rdone;!rendmoduleString=structincludeStringLabelsletequal(a:string)(b:string)=Poly.(a=b)lethash(a:string)=Hashtbl.hashaletis_empty=function|""->true|_->falseletis_prefix~prefixs=letlen_a=lengthprefixinletlen_s=lengthsiniflen_a>len_sthenfalseelseletmax_idx_a=len_a-1inletrecloopi=ifi>max_idx_athentrueelseifnot(Char.equal(unsafe_getprefixi)(unsafe_getsi))thenfalseelseloop(i+1)inloop0letis_suffix~suffixs=letlen_a=lengthsuffixinletlen_s=lengthsiniflen_a>len_sthenfalseelseletmax_idx_a=len_a-1inletrecloopi=ifi>max_idx_athentrueelseifnot(Char.equal(unsafe_getsuffix(len_a-1-i))(unsafe_gets(len_s-1-i)))thenfalseelseloop(i+1)inloop0letdrop_prefix~prefixs=letplen=String.lengthprefixinifplen>String.lengthsthenNoneelsetryfori=0toString.lengthprefix-1doifnot(Char.equals.[i]prefix.[i])thenraiseExitdone;Some(String.subsplen(String.lengths-plen))withExit->Noneletfor_all=letrecloops~f~lasti=ifi>lastthentrueelseiff(String.unsafe_getsi)thenloops~f~last(i+1)elsefalseinfuns~f->loops~f~last:(String.lengths-1)0letis_asciis=letres=reftrueinfori=0toString.lengths-1domatchs.[i]with|'\000'..'\127'->()|'\128'..'\255'->res:=falsedone;!reslethas_backslashs=letres=reffalseinfori=0toString.lengths-1doifChar.equals.[i]'\\'thenres:=truedone;!resletsplit_char~sepp=String.split_on_charsepp(* copied from https://github.com/ocaml/ocaml/pull/10 *)letsplit~seps=letsep_len=String.lengthsepinifsep_len=1thensplit_char~sep:sep.[0]selseletsep_max=sep_len-1inifsep_max<0theninvalid_arg"String.split: empty separator"elselets_max=String.lengths-1inifs_max<0then[""]elseletacc=ref[]inletsub_start=ref0inletk=ref0inleti=ref0in(* We build the substrings by running from the start of [s] to the
end with [i] trying to match the first character of [sep] in
[s]. If this matches, we verify that the whole [sep] is matched
using [k]. If this matches we extract a substring from the start
of the current substring [sub_start] to [!i - 1] (the position
before the [sep] we found). We then continue to try to match
with [i] by starting after the [sep] we just found, this is also
becomes the start position of the next substring. If [i] is such
that no separator can be found we exit the loop and make a
substring from [sub_start] until the end of the string. *)while!i+sep_max<=s_maxdoifnot(Char.equal(String.unsafe_gets!i)(String.unsafe_getsep0))thenincrielse((* Check remaining [sep] chars match, access to unsafe s (!i + !k) is
guaranteed by loop invariant. *)k:=1;while!k<=sep_max&&Char.equal(String.unsafe_gets(!i+!k))(String.unsafe_getsep!k)doincrkdone;if!k<=sep_maxthen(* no match *)incrielseletnew_sub_start=!i+sep_max+1inletsub_end=!i-1inletsub_len=sub_end-!sub_start+1inacc:=String.subs!sub_startsub_len::!acc;sub_start:=new_sub_start;i:=new_sub_start)done;List.rev(String.subs!sub_start(s_max-!sub_start+1)::!acc)letapply1f(s:string):string=letb=Bytes.of_stringsinifBytes.lengthb=0thenselse(Bytes.unsafe_setb0(f(Bytes.unsafe_getb0));Bytes.to_stringb)letlsplit2line~on:delim=tryletpos=indexlinedeliminSome(subline~pos:0~len:pos,subline~pos:(pos+1)~len:(lengthline-pos-1))withNot_found->Noneletrsplit2line~on:delim=tryletpos=rindexlinedeliminSome(subline~pos:0~len:pos,subline~pos:(pos+1)~len:(lengthline-pos-1))withNot_found->Noneletcapitalize_asciis=apply1Char.uppercase_asciisletuncapitalize_asciis=apply1Char.lowercase_asciislet[@inline]not_in_x80_to_xBFb=blsr6<>0b10let[@inline]not_in_xA0_to_xBFb=blsr5<>0b101let[@inline]not_in_x80_to_x9Fb=blsr5<>0b100let[@inline]not_in_x90_to_xBFb=b<0x90||0xBF<blet[@inline]not_in_x80_to_x8Fb=blsr4<>0x8let[@inline]utf_8_uchar_2b0b1=((b0land0x1F)lsl6)lor(b1land0x3F)let[@inline]utf_8_uchar_3b0b1b2=((b0land0x0F)lsl12)lor((b1land0x3F)lsl6)lor(b2land0x3F)let[@inline]utf_8_uchar_4b0b1b2b3=((b0land0x07)lsl18)lor((b1land0x3F)lsl12)lor((b2land0x3F)lsl6)lor(b3land0x3F)externalget_uint8:string->int->int="%string_safe_get"externalunsafe_get_uint8:string->int->int="%string_unsafe_get"letdec_invalid=Uchar.utf_decode_invalidlet[@inline]dec_retnu=Uchar.utf_decoden(Uchar.unsafe_of_intu)letget_utf_8_ucharbi=letb0=get_uint8biin(* raises if [i] is not a valid index. *)letget=unsafe_get_uint8inletmax=lengthb-1inmatchChar.unsafe_chrb0with(* See The Unicode Standard, Table 3.7 *)|'\x00'..'\x7F'->dec_ret1b0|'\xC2'..'\xDF'->leti=i+1inifi>maxthendec_invalid1elseletb1=getbiinifnot_in_x80_to_xBFb1thendec_invalid1elsedec_ret2(utf_8_uchar_2b0b1)|'\xE0'->leti=i+1inifi>maxthendec_invalid1elseletb1=getbiinifnot_in_xA0_to_xBFb1thendec_invalid1elseleti=i+1inifi>maxthendec_invalid2elseletb2=getbiinifnot_in_x80_to_xBFb2thendec_invalid2elsedec_ret3(utf_8_uchar_3b0b1b2)|'\xE1'..'\xEC'|'\xEE'..'\xEF'->leti=i+1inifi>maxthendec_invalid1elseletb1=getbiinifnot_in_x80_to_xBFb1thendec_invalid1elseleti=i+1inifi>maxthendec_invalid2elseletb2=getbiinifnot_in_x80_to_xBFb2thendec_invalid2elsedec_ret3(utf_8_uchar_3b0b1b2)|'\xED'->leti=i+1inifi>maxthendec_invalid1elseletb1=getbiinifnot_in_x80_to_x9Fb1thendec_invalid1elseleti=i+1inifi>maxthendec_invalid2elseletb2=getbiinifnot_in_x80_to_xBFb2thendec_invalid2elsedec_ret3(utf_8_uchar_3b0b1b2)|'\xF0'->leti=i+1inifi>maxthendec_invalid1elseletb1=getbiinifnot_in_x90_to_xBFb1thendec_invalid1elseleti=i+1inifi>maxthendec_invalid2elseletb2=getbiinifnot_in_x80_to_xBFb2thendec_invalid2elseleti=i+1inifi>maxthendec_invalid3elseletb3=getbiinifnot_in_x80_to_xBFb3thendec_invalid3elsedec_ret4(utf_8_uchar_4b0b1b2b3)|'\xF1'..'\xF3'->leti=i+1inifi>maxthendec_invalid1elseletb1=getbiinifnot_in_x80_to_xBFb1thendec_invalid1elseleti=i+1inifi>maxthendec_invalid2elseletb2=getbiinifnot_in_x80_to_xBFb2thendec_invalid2elseleti=i+1inifi>maxthendec_invalid3elseletb3=getbiinifnot_in_x80_to_xBFb3thendec_invalid3elsedec_ret4(utf_8_uchar_4b0b1b2b3)|'\xF4'->leti=i+1inifi>maxthendec_invalid1elseletb1=getbiinifnot_in_x80_to_x8Fb1thendec_invalid1elseleti=i+1inifi>maxthendec_invalid2elseletb2=getbiinifnot_in_x80_to_xBFb2thendec_invalid2elseleti=i+1inifi>maxthendec_invalid3elseletb3=getbiinifnot_in_x80_to_xBFb3thendec_invalid3elsedec_ret4(utf_8_uchar_4b0b1b2b3)|_->dec_invalid1letfold_utf_8s~facc=letrecloopis~pos~facc=ifString.lengths=posthenaccelseletr=get_utf_8_ucharsposinletl=Uchar.utf_decode_lengthrinletacc=facci(Uchar.utf_decode_ucharr)inloop(i+1)s~pos:(pos+l)~faccinloop0s~pos:0~faccletfix_utf_8s=letb=Buffer.create(String.lengths)infold_utf_8s()~f:(fun()_iu->Buffer.add_utf_8_ucharbu);Buffer.contentsbletis_valid_utf_8b=letrecloopmaxbi=ifi>maxthentrueelseletget=unsafe_get_uint8inmatchChar.unsafe_chr(getbi)with|'\x00'..'\x7F'->loopmaxb(i+1)|'\xC2'..'\xDF'->letlast=i+1iniflast>max||not_in_x80_to_xBF(getblast)thenfalseelseloopmaxb(last+1)|'\xE0'->letlast=i+2iniflast>max||not_in_xA0_to_xBF(getb(i+1))||not_in_x80_to_xBF(getblast)thenfalseelseloopmaxb(last+1)|'\xE1'..'\xEC'|'\xEE'..'\xEF'->letlast=i+2iniflast>max||not_in_x80_to_xBF(getb(i+1))||not_in_x80_to_xBF(getblast)thenfalseelseloopmaxb(last+1)|'\xED'->letlast=i+2iniflast>max||not_in_x80_to_x9F(getb(i+1))||not_in_x80_to_xBF(getblast)thenfalseelseloopmaxb(last+1)|'\xF0'->letlast=i+3iniflast>max||not_in_x90_to_xBF(getb(i+1))||not_in_x80_to_xBF(getb(i+2))||not_in_x80_to_xBF(getblast)thenfalseelseloopmaxb(last+1)|'\xF1'..'\xF3'->letlast=i+3iniflast>max||not_in_x80_to_xBF(getb(i+1))||not_in_x80_to_xBF(getb(i+2))||not_in_x80_to_xBF(getblast)thenfalseelseloopmaxb(last+1)|'\xF4'->letlast=i+3iniflast>max||not_in_x80_to_x8F(getb(i+1))||not_in_x80_to_xBF(getb(i+2))||not_in_x80_to_xBF(getblast)thenfalseelseloopmaxb(last+1)|_->falseinloop(lengthb-1)b0letfold_left~f~inits=letr=refinitinfori=0tolengths-1dor:=f!r(unsafe_getsi)done;!rletfold_right~fs~init=letr=refinitinfori=lengths-1downto0dor:=f(unsafe_getsi)!rdone;!rendmoduleUtf8_string:sigtypet=privateUtf8ofstring[@@ocaml.unboxed]valof_string_exn:string->tvalcompare:t->t->intvalequal:t->t->boolend=structtypet=Utf8ofstring[@@ocaml.unboxed]letof_string_exns=ifString.is_valid_utf_8sthenUtf8selseinvalid_arg"Utf8_string.of_string: invalid utf8 string"letcompare(Utf8x)(Utf8y)=String.comparexyletequal(Utf8x)(Utf8y)=String.equalxyendmoduleInt=structtypet=intletcompare(x:int)y=comparexyletequal(x:t)y=x=ylethash(x:t)=Hashtbl.hashxendmoduleIntSet=Set.Make(Int)moduleIntMap=Map.Make(Int)moduleStringSet=Set.Make(String)moduleStringMap=Map.Make(String)moduleUtf8_string_set=Set.Make(Utf8_string)moduleUtf8_string_map=Map.Make(Utf8_string)moduleBitSet:sigtypetvalcreate:unit->tvalcreate':int->tvalmem:t->int->boolvalset:t->int->unitvalunset:t->int->unitvalcopy:t->tvaliter:f:(int->unit)->t->unitvalsize:t->intvalnext_free:t->int->intvalnext_mem:t->int->intend=structtypet={mutablearr:intarray}letcreate()={arr=Array.make10}letcreate'n={arr=Array.make((n/int_num_bits)+1)0}letsizet=Array.lengtht.arr*int_num_bitsletmemti=letarr=t.arrinletidx=i/int_num_bitsinletoff=imodint_num_bitsinidx<Array.lengtharr&&letx=Array.unsafe_getarridxinx<>0&&xland(1lsloff)<>0let[@ocaml.inlinenever]resizetidx=letsize=Array.lengtht.arrinletsize_ref=refsizeinwhileidx>=!size_refdosize_ref:=!size_ref*2done;leta=Array.make!size_ref0inArray.blitt.arr0a0size;t.arr<-aletsetti=letidx=i/int_num_bitsinletoff=imodint_num_bitsinletsize=Array.lengtht.arrinifidx>=sizethenresizetidx;Array.unsafe_sett.arridx(Array.unsafe_gett.arridxlor(1lsloff))letunsetti=letidx=i/int_num_bitsinletoff=imodint_num_bitsinletsize=Array.lengtht.arrinifidx>=sizethen()elseletb=Array.unsafe_gett.arridxinletmask=1lsloffinifb<>0&&blandmask<>0thenArray.unsafe_sett.arridx(blxormask)letnext_freeti=letx=refiinwhilememt!xdoincrxdone;!xletnext_memti=letx=refiinwhilenot(memt!x)doincrxdone;!xletcopyt={arr=Array.copyt.arr}letiter~ft=fori=0tosizetdoifmemtithenfidoneendmoduleArray=structincludeArrayLabelsletfind_opt~f:pa=letn=lengthainletrecloopi=ifi=nthenNoneelseletx=unsafe_getaiinifpxthenSomexelseloop(succi)inloop0letfold_right_ia~f~init:x=letr=refxinfori=Array.lengtha-1downto0dor:=fi(Array.unsafe_getai)!rdone;!rletequaleqab=letlen_a=Array.lengthainiflen_a<>Array.lengthbthenfalseelseleti=ref0inwhile!i<len_a&&eqa.(!i)b.(!i)doincridone;!i=len_aendmoduleFilename=structincludeFilenamelettemp_file_name=(* Inlined unavailable Filename.temp_file_name. Filename.temp_file gives
us incorrect permissions. https://github.com/ocsigen/js_of_ocaml/issues/182 *)letprng=lazy(Random.State.make_self_init())infun~temp_dirprefixsuffix->letrnd=Random.State.bits(Lazy.forceprng)land0xFFFFFFinFilename.concattemp_dir(Printf.sprintf"%s%06x%s"prefixrndsuffix)letgen_filefilef=letf_tmp=temp_file_name~temp_dir:(Filename.dirnamefile)(Filename.basenamefile)".tmp"intryletch=open_out_binf_tmpinletres=tryfchwithe->close_outch;raiseeinclose_outch;(trySys.removefilewithSys_error_->());Sys.renamef_tmpfile;reswithexc->Sys.removef_tmp;raiseexcendmoduleFun=structincludeFunletmemoizef=leth=Hashtbl.create4infunx->tryHashtbl.findhxwithNot_found->letr=fxinHashtbl.addhxr;rendletgenerated_name=function|"param"|"match"|"switcher"->true|s->String.is_prefix~prefix:"cst_"s