Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file stog_ocaml_session_main.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256(*********************************************************************************)(* Stog *)(* *)(* Copyright (C) 2012-2015 INRIA All rights reserved. *)(* Author: Maxence Guesdon, INRIA Saclay *)(* *)(* This program is free software; you can redistribute it and/or modify *)(* it under the terms of the GNU General Public License as *)(* published by the Free Software Foundation, version 3 of the License. *)(* *)(* 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 General Public License for more details. *)(* *)(* You should have received a copy of the GNU 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 *)(* *)(* As a special exception, you have permission to link this program *)(* with the OCaml compiler and distribute executables, as long as you *)(* follow the requirements of the GNU GPL in regard to all of the *)(* software in the executable aside from the OCaml compiler. *)(* *)(* Contact: Maxence.Guesdon@inria.fr *)(* *)(*********************************************************************************)openStog_base.Ocaml_types;;(* must be done after parsing options, for example -safe-string *)letinit_toplevel()=Toploop.set_paths();Toploop.initialize_toplevel_env();let_=matchHashtbl.findToploop.directive_table"rectypes"withToploop.Directive_nonef->f()|_->assertfalseinToploop.max_printer_steps:=20(*let _ = Location.input_name := "";;*)letstderr_file=Filename.temp_file"stogocamlsession""err";;letstdout_file=Filename.temp_file"stogocamlsession""out";;letlog_file=Filename.temp_file"stogocamlsession""log";;letlog_oc=open_outlog_file;;letlogs=output_stringlog_ocs;output_stringlog_oc"\n";;letremove_empty_filename=letempty="File \"\", l"inletempty_none="File \"_none_\", l"inletre=Str.regexp_stringemptyinletre_none=Str.regexp_stringempty_noneinfuns->Str.global_replacere_none"L"(Str.global_replacere"L"s);;exceptionPp_errorofstringletapply_ppphrase=match!Clflags.preprocessorwith|None->phrase|Somepp->letfile=Filename.temp_file"stogocamlsession""pp"inletoutfile=file^".out"inStog_base.Misc.file_of_string~filephrase;letcom=Printf.sprintf"cat %s | %s > %s"(Filename.quotefile)pp(Filename.quoteoutfile)inmatchSys.commandcomwith0->letphrase=Stog_base.Misc.string_of_fileoutfileinSys.removefile;Sys.removeoutfile;phrase|n->raise(Pp_errorcom)letapply_ppxphrase=matchphrasewith|Parsetree.Ptop_dir_->phrase|Parsetree.Ptop_defstr->log"applying ppx";letstr=Pparse.apply_rewriters_str~tool_name:Sys.argv.(0)strinParsetree.Ptop_defstrleteval_ocaml_phrasephrase=tryletphrase=apply_ppphraseinletlexbuf=Lexing.from_stringphraseinletfd_err=Unix.openfilestderr_file[Unix.O_WRONLY;Unix.O_CREAT;Unix.O_TRUNC]0o640inUnix.dup2fd_errUnix.stderr;letfd_out=Unix.openfilestdout_file[Unix.O_WRONLY;Unix.O_CREAT;Unix.O_TRUNC]0o640inUnix.dup2fd_outUnix.stdout;Unix.closefd_out;log("executing phrase: "^phrase);letphrase=!Toploop.parse_toplevel_phraselexbufinlog"phrase parsed";letphrase=apply_ppxphraseinletok=Toploop.execute_phrasetrueFormat.str_formatterphraseinletoutput={topout=Format.flush_str_formatter();stderr=remove_empty_filename(Stog_base.Misc.string_of_filestderr_file);stdout=Stog_base.Misc.string_of_filestdout_file;}inlog("exec_output: "^output.topout);log("err: "^output.stderr);log("out: "^output.stdout);ifokthenStog_base.Ocaml_types.OkoutputelseStog_base.Ocaml_types.Handled_erroroutputwith|e->(* Errors.report_error relies on exported compiler lib; on some
bugged setups, those libs are not in synch with the compiler
implementation, and the call below fails
because of an implementation mismatch with the toplevel.
We are therefore extra careful when calling
Errors.report_error, and in particular collect backtraces to
help spot this vicious issue. *)letbacktrace_enabled=Printexc.backtrace_status()inifnotbacktrace_enabledthenPrintexc.record_backtracetrue;begintryErrors.report_errorFormat.str_formatterewithexn->log("an error happened during phrase error reporting:\n"^(Printexc.to_stringexn));log("error backtrace:\n%s"^(Printexc.get_backtrace()));end;ifnotbacktrace_enabledthenPrintexc.record_backtracefalse;leterr=Format.flush_str_formatter()inStog_base.Ocaml_types.Exc(Stog_base.Misc.strip_string(remove_empty_filenameerr));;letevalinput=tryletres=eval_ocaml_phraseinput.Stog_base.Ocaml_types.in_phraseinreswithe->raisee;;letadd_directory=matchHashtbl.findToploop.directive_table"directory"with|Toploop.Directive_stringf->f|_->failwith"Bad directive \"directory\""|exceptionNot_found->failwith"Directive \"directory\" not found";;letoption_packages=letpackages=String.concat" "(Stog_base.Misc.split_strings[','])inlettemp_file=Filename.temp_file"stogocamlsession"".txt"inletcom=Printf.sprintf"ocamlfind query -r %s | sort -u > %s"packages(Filename.quotetemp_file)inmatchSys.commandcomwith0->letdirs=Stog_base.Misc.split_string(Stog_base.Misc.string_of_filetemp_file)['\n';'\r']inList.iteradd_directorydirs;(trySys.removetemp_filewith_->())|n->(trySys.removetemp_filewith_->());failwith(Printf.sprintf"Command %S failed with error code %d"comn);;letparse_options()=letusage=Printf.sprintf"Usage: %s [options]\nwhere options are:"Sys.argv.(0)inArg.parse["-I",Arg.Stringadd_directory,"<dir> add <dir> to the list of include directories";"-safe-string",Arg.ClearClflags.unsafe_string," Make strings immutable";"-unsafe-string",Arg.SetClflags.unsafe_string," Make strings mutable (default)";"-pp",Arg.String(funpp->Clflags.preprocessor:=Somepp),"<command> Pipe sources through preprocessor <command>";"-ppx",Arg.String(funppx->Clflags.all_ppx:=!Clflags.all_ppx@[ppx]),"<command> Pipe abstract syntax trees through preprocessor <command>";"-package",Arg.Stringoption_package,"<pkg1[,pkg2[,...]]> add ocamlfind packages to the list of include directories";"-w",Arg.String(Warnings.parse_optionsfalse),"<list> Enable or disable warnings according to <list>";"-warn-error",Arg.String(Warnings.parse_optionstrue),"<list> Enable or disable error status for warnings according to <list>";](fun_->())usage;;letmain()=parse_options();init_toplevel();letic_input=Unix.in_channel_of_descr(Unix.dupUnix.stdin)inletoc_result=Unix.out_channel_of_descr(Unix.dupUnix.stdout)inletold_stderr=Unix.out_channel_of_descr(Unix.dupUnix.stderr)inletrecloop()=letfinish=tryletinput=Stog_base.Ocaml_types.read_inputic_inputinletres=evalinputinStog_base.Ocaml_types.write_resultoc_resultres;falsewithEnd_of_file|Failure_->(* since ocaml 4.03.0 input_value raise Failure instead of EOF *)true|e->letmsg=matchewithPp_errorcom->(Printf.sprintf"Preprocess command failed: %s"com)|e->Printexc.to_stringeinoutput_stringold_stderrmsg;flushold_stderr;falseinifnotfinishthenloop()inloop();close_outoc_result;;trymain();List.iter(funf->trySys.removefwith_->())[stderr_file;stdout_file;log_file]withSys_errors|Failures->prerr_endlines;exit1|e->prerr_endline(Printexc.to_stringe);exit1;;