Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file comopt.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228(* command line argument spec *)openBasemoduleHashtbl=structincludeHashtblincludeXhashtblendmoduleList=structincludeListincludeXlistendtype('a,'err)opt={short:charoption;long:stringoption;arg:[`Nullaryof'a|`Unaryof(string->('a,'err)Vresult.t)]}(*
let opt_to_string opt =
match opt.short, opt.long with
| None, None -> assert false
(* nullary *)
| Some short, None -> " -%c %s"
| Some short, Some long -> " -%c, --%s %s"
| None, Some long -> " --%s %s"
| Some short, None -> " -%c XXX %s"
| Some short, Some long -> " -%c, --%s=XXX %s"
| None, Some long -> " --%s=XXX %s"
*)moduleError=structtypet=[`Ambiguousofstring*string*string|`Requires_argumentofstring|`Nullary_takes_argumentofstring|`Unknownofstring]letto_string=function|`Ambiguous(sw,k1,k2)->!%"Switch --%s is ambigous: it may be --%s or --%s"swk1k2|`Requires_argumentsw->!%"Switch %s requires an argument"sw|`Nullary_takes_argumentsw->!%"Switch %s does not take an argument"sw|`Unknownsw->!%"Unknown switch %s"swendletnullaryshortlongarg=matchshort,longwith|None,None->assertfalse|_->{short;long;arg=`Nullaryarg}letunaryshortlongarg=matchshort,longwith|None,None->assertfalse|_->{short;long;arg=`Unaryarg}type('a,'err)t={shorts:(char,('a,'err)opt)Hashtbl.t;longs:(string*('a,'err)opt)list;}letmakeopts=letshorts=Hashtbl.create107inList.iter(function|{short=None}->()|({short=Somec}aso)->Hashtbl.altershortsc(function|Some_->assertfalse|None->Someo))opts;letlongs=List.filter_map(function|{long=None}->None|({long=Somes}aso)->Some(s,o))optsinletkeys=List.mapfstlongsinletreccheckst=function|[]->()|x::_whenList.memxst->assertfalse|x::xs->check(x::st)xsincheck[]keys;{shorts;longs}letstring_tailsfrom=String.subsfrom(String.lengths-from)letrecparsetst=function|[]->Ok(List.revst)|arg::args->matchargwith|_whenString.lengtharg=1->parset(`Anonarg::st)args|"--"->Ok(List.rev_appendst(List.map(funx->`Anonx)args))|_->matcharg.[0],arg.[1]with|'\\','-'->parset(`Anon(string_tailarg1)::st)args|'-','-'->parse_long_switchtst(string_tailarg2)args|'-',_->parse_short_switchtst(string_tailarg1)args|_->parset(`Anonarg::st)argsandparse_short_switchtstswargs=letlen=String.lengthswinletrecparse_swstchar_pos=iflen<=char_posthenparsetstargselseletsw_char=sw.[char_pos]intryletswitch=Hashtbl.findt.shortssw_charinmatchswitch.argwith|`Unaryfwhenlen=char_pos+1->get_parametertstf(!%"-%c"sw_char)args|`Unary_->Error(`Requires_argument(!%"-%c"sw_char))|`Nullaryv->parse_sw(v::st)(char_pos+1)with|Not_found->Error(`Unknown(!%"-%c"sw_char))inparse_swst0andget_parametertstfname=function|[]->Error(`Requires_argumentname)|arg::args->matchfargwith|Okv->parset(v::st)args|Errore->Erroreandparse_long_switchtstswargs=letsw,param=tryletpos=String.indexsw'='inString.subsw0pos,Some(string_tailsw(pos+1))with|Not_found->sw,Noneinletdo_found=function|None->Error(`Unknown("--"^sw))|Some(`Matchswitch|`Partial(_,switch))->matchswitch.arg,paramwith|`Unaryf,Someparam->beginmatchfparamwith|Okv->parset(v::st)args|Errore->Erroreend|`Nullaryv,None->parset(v::st)args|`Nullary_,Some_->Error(`Nullary_takes_argument("--"^sw))|`Unary_,None->Error(`Requires_argument("--"^sw))inletrecfindfound=function|[]->do_foundfound|(k,switch)::kss->letmatch_=ifsw=kthen`Matchelsetryifsw=String.subk0(String.lengthsw)then`Partialelse`No_matchwith_->`No_matchinmatchmatch_,foundwith|`Match,_->do_found(Some(`Matchswitch))|`Partial,None->find(Some(`Partial(k,switch)))kss|`Partial,(Some(`Match_))->findfoundkss|`Partial,(Some(`Partial(k',_)))->Error(`Ambiguous(sw,k,k'))|`No_match,_->findfoundkssinfindNonet.longsletparseoptsargs=parse(makeopts)[]argslet%TESTlong_amb_nullary_=letlong1=nullaryNone(Some"long")`Longinletlong2=nullaryNone(Some"lo")`Loinmatchparse[long1;long2]["--long";"--lon";"--lo"]with|Ok[`Long;`Long;`Lo]->()|Ok_->assertfalse|Error_->assertfalselet%TESTlong_amb_unary_=letlong1=unaryNone(Some"long")(funx->Ok(`Longx))inletlong2=unaryNone(Some"lo")(funx->Ok(`Lox))inmatchparse[long1;long2]["--long=x";"--lon=x";"--lo=x"]with|Ok[`Long"x";`Long"x";`Lo"x"]->()|Ok_->assertfalse|Error_->assertfalselet%TESTlong_unary_without_arg_=letlong=unaryNone(Some"long")(funx->Ok(`Longx))inmatchparse[long]["--long"]with|Error(`Requires_argument"--long")->()|_->assertfalselet%TESTlong_nullary_with_arg_=letlong=nullaryNone(Some"long")`Longinmatchparse[long]["--long=x"]with|Error(`Nullary_takes_argument"--long")->()|_->assertfalselet%TESTlong_amb_unary_error_=letlong1=unaryNone(Some"long")(funx->Ok(`Longx))inletlong2=unaryNone(Some"lo")(funx->Ok(`Lox))inmatchparse[long1;long2]["--l=x"]with|Error(`Ambiguous("l",_,_))->()|_->assertfalselet%TESTlong_amb_nullary_error_=letlong1=nullaryNone(Some"long")`Longinletlong2=nullaryNone(Some"lo")`Loinmatchparse[long1;long2]["--l"]with|Error(`Ambiguous("l",_,_))->()|_->assertfalselet%TESTshort_unary_without_arg_=letshort1=unary(Some'x')None(funx->Ok(`Xx))inmatchparse[short1]["-x"]with|Error(`Requires_argument"-x")->()|_->assertfalselet%TESTshort_unary_without_arg2_=letshort1=unary(Some'x')None(funx->Ok(`Xx))inletshort2=unary(Some'z')None(funx->Ok(`Zx))inmatchparse[short1;short2]["-xz";"hello"]with|Error(`Requires_argument"-x")->()|_->assertfalselet%TESTshort_nullary_many_=letshort_a=nullary(Some'a')None`ainletshort_b=nullary(Some'b')None`binletshort_c=nullary(Some'c')None`cinmatchparse[short_a;short_b;short_c]["-abcba";"hello"]with|Ok[`a;`b;`c;`b;`a;`Anon"hello"]->()|_->assertfalse