123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169(************************************************************************)(* * The Coq Proof Assistant / The Coq Development Team *)(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)(* <O___,, * (see CREDITS file for the list of authors) *)(* \VV/ **************************************************************)(* // * This file is distributed under the terms of the *)(* * GNU Lesser General Public License Version 2.1 *)(* * (see LICENSE file for the text of the license) *)(************************************************************************)(************************************************************************)(* Coq serialization API/Plugin *)(* Copyright 2016-2018 MINES ParisTech -- Dual License LGPL 2.1 / GPL3+ *)(* Written by: Emilio J. Gallego Arias *)(************************************************************************)(* Status: Very Experimental *)(************************************************************************)openSexplibopenSexplib.ConvmoduleSP=Serapi_protocol(******************************************************************************)(* Global Protocol Options *)(******************************************************************************)typeser_opts={in_chan:in_channel(* Input/Output channels *);out_chan:out_channel(* Printers *);printer:Sertop_ser.ser_printer;debug:bool;print0:bool;lheader:bool(* Print lenght header (deprecated) *)(* Coq options *);no_init:bool(* Whether to create the initial document *);no_prelude:bool(* Whether to load stdlib's prelude *);topfile:stringoption(* Top name is derived from topfile name *);loadpath:Mltop.coq_pathlist(* From -R and -Q options usually *);async:Sertop_init.async_flags}(******************************************************************************)(* Input/Output *)(******************************************************************************)(* *)(* Until this point, we've been independent of a particular format or *)(* or serialization, with all the operations defined at the symbolic level. *)(* *)(* It is now time to unfortunately abandon our fairy-tale and face the real, *)(* ugly world in these last 40 lines! *)(* *)(******************************************************************************)letis_cmd_quitcmd=matchcmdwith|SP.Quit->true|_->false(* XXX: Improve by using manual tag parsing. *)letread_cmdcmd_idin_channelpp_error=letrecread_loop()=tryletcmd_sexp=Sexp.input_sexpin_channelinbegintrySertop_ser.tagged_cmd_of_sexpcmd_sexpwith|End_of_file->"EOF",SP.Quit|_exn->(string_of_intcmd_id),Sertop_ser.cmd_of_sexpcmd_sexpendwith|End_of_file->"EOF",SP.Quit|exn->pp_error(sexp_of_exnexn);read_loop()inread_loop()letout_sexpopts=letopenFormatinletpp_sexp=Sertop_ser.select_printeropts.printerinletpp_term=ifopts.print0thenfunfmt()->fprintffmt"%c"(Char.chr0)elsefunfmt()->fprintffmt"@\n"inifopts.lheaderthenfunfmta->fprintfstr_formatter"@[%a@]%a%!"pp_sexpapp_term();letout=flush_str_formatter()infprintffmt"@[byte-length: %d@\n%s@]%!"(String.lengthout)outelsefunfmta->fprintffmt"@[%a@]%a%!"pp_sexpapp_term()(** We could use Sexp.to_string too *)letout_answeropts=letpp_sexp=out_sexpoptsinfunfmta->pp_sexpfmt(Sertop_ser.sexp_of_answera)(** Set the topname from optional topfile string or default if None **)letdoc_typetopfile=matchtopfilewith|None->letsertop_dp=Names.(DirPath.make[Id.of_string"SerTop"])inStm.Interactive(TopLogicalsertop_dp)|Somefilename->Stm.VoDocfilenameletser_loopser_opts=letopenListinletopenFormatin(* XXX EG: I don't understand this well, why is this lock needed ??
Review fork code in CoqworkmgrApi *)letpr_mutex=Mutex.create()inletser_lockfx=Mutex.lockpr_mutex;fx;Mutex.unlockpr_mutexinletout_fmt=formatter_of_out_channelser_opts.out_chaninletpp_answer=ser_lock(out_answerser_optsout_fmt)inletpp_err=ser_lock(out_sexpser_optsout_fmt)inletpp_ackcid=pp_answer(SP.Answer(cid,SP.Ack))inletpp_optfb=Sertop_util.feedback_opt_filterfbinletpp_feedfb=Option.iter(funfb->pp_answer(SP.Feedback(Sertop_util.feedback_trfb)))(pp_optfb)in(* Init Coq *)let()=Sertop_init.(coq_init{fb_handler=pp_feed;ml_load=None;debug=ser_opts.debug})in(* Follow the same approach than coqtop for now: allow Coq to be
* interrupted by Ctrl-C. Not entirely safe or race free... but we
* trust the IDEs to send the signal on coherent IO state.
*)Sys.catch_breaktrue;letrequire_libs=ifser_opts.no_preludethen[]else["Coq.Init.Prelude",None,Somefalse]inletiload_path=ser_opts.loadpathinletstm_options=Sertop_init.process_stm_flagsser_opts.asyncinifnotser_opts.no_initthenbeginletndoc={Stm.doc_type=doc_typeser_opts.topfile;require_libs;iload_path;stm_options}inlet_=Stm.new_docndocin()end;(* Main loop *)letrecloopcmd_id=tryletcmd_tag,cmd=read_cmdcmd_idser_opts.in_chanpp_errinpp_ackcmd_tag;iterpp_answer@@map(funa->SP.Answer(cmd_tag,a))(SP.exec_cmdcmd);ifnot(is_cmd_quitcmd)thenloop(1+cmd_id)withSys.Break->loop(1+cmd_id)inloop0