123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187(************************************************************************)(* * 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 Language Server Protocol *)(* Copyright 2019 MINES ParisTech -- Dual License LGPL 2.1 / GPL3+ *)(* Copyright 2019-2024 Inria -- Dual License LGPL 2.1 / GPL3+ *)(* Written by: Emilio J. Gallego Arias & Bhakti Shah *)(************************************************************************)moduleDefMap=CString.MapmoduleError=structtypet=|Ill_formedofstring|Outdatedletto_string=function|Ill_formeds->"Ill-formed file: "^s|Outdated->"Outdated .glob file"endmoduleInfo=structtypet={kind:string;offset:int*int}end(* This is taken from coqdoc/glob_file.ml , we should share this code, but no
cycles ATM *)moduleCoq=structmoduleEntry_type=structtypet=|Library|Module|Definition|Inductive|Constructor|Lemma|Record|Projection|Instance|Class|Method|Variable|Axiom|TacticDefinition|Abbreviation|Notation|Section|Binderletof_string=function|"def"|"coe"|"subclass"|"canonstruc"|"fix"|"cofix"|"ex"|"scheme"->Definition|"prf"|"thm"->Lemma|"ind"|"variant"|"coind"->Inductive|"constr"->Constructor|"indrec"|"rec"|"corec"->Record|"proj"->Projection|"class"->Class|"meth"->Method|"inst"->Instance|"var"->Variable|"defax"|"prfax"|"ax"->Axiom|"abbrev"|"syndef"->Abbreviation|"not"->Notation|"lib"->Library|"mod"|"modtype"->Module|"tac"->TacticDefinition|"sec"->Section|"binder"->Binder|s->invalid_arg("type_of_string:"^s)endletread_dpic=letline=input_lineicinletn=String.lengthlineinmatchline.[0]with|'F'->letlib_name=String.subline1(n-1)inOklib_name|_->Error(Error.Ill_formed"lib name not found in header")letcorrect_filevfileic=lets=input_lineicinifString.lengths<7||String.subs07<>"DIGEST "thenError(Error.Ill_formed"DIGEST ill-formed")elselets=String.subs7(String.lengths-7)inmatch(vfile,s)with|None,"NO"->read_dpic|Some_,"NO"->Error(Ill_formed"coming from .v file but no digest")|None,_->Error(Ill_formed"digest but .v source file not available")|Somevfile,s->ifs=Digest.to_hex(Digest.filevfile)then(* XXX Read F line *)read_dpicelseErrorOutdatedletparse_refline=try(* Disable for now *)iffalsethenletadd_ref_____=()inScanf.sscanfline"R%d:%d %s %s %s %s"(funloc1loc2lib_dpspidty->forloc=loc1toloc2doadd_refloclib_dpspid(Entry_type.of_stringty);(* Also add an entry for each module mentioned in [lib_dp], * to
use in interpolation. *)ignore(List.fold_right(funthisPiecepriorPieces->letnewPieces=matchpriorPieceswith|""->thisPiece|_->thisPiece^"."^priorPiecesinadd_refloc""""newPiecesEntry_type.Library;newPieces)(Str.split(Str.regexp_string".")lib_dp)"")done)with_->()letparse_defline:_Result.t=tryScanf.sscanfline"%s %d:%d %s %s"(funkindloc1loc2section_pathname->Ok(name,section_path,kind,(loc1,loc2)))withScanf.Scan_failureerr->Errorerrletprocess_linedpmapline=matchline.[0]with|'R'->let_reference=parse_reflineinmap|_->(matchparse_deflinewith|Error_->map|Ok(name,section_path,kind,offset)->letsection_path=ifString.equal"<>"section_paththen""elsesection_path^"."inletname=dp^"."^section_path^nameinletinfo={Info.kind;offset}inDefMap.addnameinfomap)letread_globvfileinc=matchcorrect_filevfileincwith|Errore->Error(Error.to_stringe)|Okdp->(letmap=refDefMap.emptyintrywhiletruedoletline=input_lineincinletn=String.lengthlineinifn>0thenmap:=process_linedp!maplinedone;assertfalsewithEnd_of_file->Ok!map)end(* Glob file that was read and parsed successfully *)typet=Info.tDefMap.tletopen_filefile=ifSys.file_existsfilethenletvfile=Filename.remove_extensionfile^".v"inCompat.Ocaml_414.In_channel.with_open_textfile(Coq.read_glob(Somevfile))elseError(Format.asprintf"Cannot open file: %s"file)letget_infomapname=DefMap.find_optnamemap