123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133(* This file is free software, part of dolmen. See file "LICENSE" for more information *)(* Exit codes *)(* ************************************************************************* *)typet={mutablecode:int;(* codes are set later (to accomodate users of the lib choosing error codes
that do not conflict with theirs), and should be unique for each exit code *)descr:string;category:string;mutableabort:bool;}lethasht=t.codeletequaltt'=t.code=t'.codeletcomparett'=comparet.codet'.codeletdescrt=t.code,t.descrletcategoryt=t.category(* Setting exact return codes *)(* ************************************************************************* *)(* cmdliner uses codes 123, 124 and 125, and codes greater then 125 are
usually reserved for the shells. *)letmax_code=122letall_errors=ref[]letcode_array=Array.make(max_code+1)Noneletcode_usedcode=code<=0||code>max_code||matchcode_array.(code)with|Some_->true|None->falseletfind_code()=leti=ref1inwhile!i<=max_code&&code_used!idoi:=!i+1done;if!i>max_codethenassertfalse(* no available error code *)else!iletset_retcode(t,code)=assert(t.code=-1);assert(not(code_usedcode));code_array.(code)<-Somet;t.code<-code;()letinit?(full=false)l=List.iterset_retcodel;List.iter(funt->ift.code<0thenbeginiffullthenfailwith"partial retcode init"elsebeginletcode=find_code()inset_retcode(t,code)endend)(List.rev!all_errors)(* Exit with a code and code status *)(* ************************************************************************* *)letis_abortt=t.abortletabortt=t.abort<-trueleterrort=t.abort<-falseletexitt=ift.code<0thenfailwith"missing retcode"elseift.abortthen(Unix.kill(Unix.getpid())Sys.sigabrt;assertfalse)elseexitt.code(* Manipulation *)(* ************************************************************************* *)(* The create function should only be used for error exit codes,
the ok exit code (i.e. [0]) is create manually and not included
in the errors list. *)letcreate~category~descr=lett={code=-1;abort=false;descr;category;}inall_errors:=t::!all_errors;t(* *)leterrors()=List.rev!all_errors(* Special values *)(* ************************************************************************* *)letok={code=0;descr="the success exit code";category="N/A";abort=false;}letbug={code=125;descr="on unexpected internal errors (bugs)";category="Internal";abort=false;}(* Predefined values *)(* ************************************************************************* *)letgeneric=create~category:"Generic"~descr:"on generic error"letlimit=create~category:"Limits"~descr:"upon reaching limits (time, memory, etc..)"letparsing=create~category:"Parsing"~descr:"on parsing errors"lettyping=create~category:"Typing"~descr:"on typing errors"