%------------------------------------------------------------------------------% % Copyright (C) 1999-2001 INRIA/INSA de Rennes/IFSIC. % This file may only be copied under the terms of the GNU Library General % Public License - see the file License in the Morphine distribution. % % Author : Erwan Jahier % % Morphine built-ins, primitives and commands related to coprocessing % in the Morphine process (part of scenario morphine_kernel.op). %------------------------------------------------------------------------------% %:- pred start_connection(atom, atom, atom). %:- mode start_connection(in, out) is det. % To start the connection with the Mercury process start_connection(ProgramName, SockId2) :- write("Start debugging "), write(ProgramName), write(" program.\n"), get_parameter(socket_domain, [SocketDomain]), ( (SocketDomain = unix) -> % construct the socket address (ex: /tmp/soc1233) construct_socket_address(SockAddPidStr), atom_string(SockId, SockAddPidStr), socket(unix, stream, sock) ; % socket_type = inet socket(internet, stream, sock) ), % clean up unused socket addresses kill_all_socket_address, % Bind the socket name to the socket bind(sock, SockId), ( (SocketDomain = unix) -> SockId2 = SockId ; SockId = _ / SockId2 ), listen(sock, 1). construct_socket_address(Addr) :- mercury_morphine_socket_address(Addr0), append_strings(Addr0, "soc", Addr1), % We add the pid to the socket path name to make sure that 2 users on % the same machine can use Morphine simultaneously. get_flag(pid, Pid), number_string(Pid, PidStr), append_strings(Addr1, PidStr, Addr), % Record the socket address to be able to delete it later setval(socket_address_str, SockAddPidStr). %------------------------------------------------------------------------------% opium_primitive( name : end_connection, arg_list : [], arg_type_list : [], abbrev : ec, implementation : end_connection_Op, message : 'Ends the connection with the traced program.' ). % :- pred end_connection is det. end_connection_Op :- kill_all_socket_address, setval(state_of_morphine, not_running), close(sock), close(newsock), write("End of connection with the traced program\n"). kill_all_socket_address :- get_flag(pid, Pid), number_string(Pid, PidStr), append_strings("*", PidStr, StarPidStr), mercury_morphine_socket_address(AddressStr), append_strings("rm -f ", AddressStr, C), append_strings(C, StarPidStr, Command), morphine_write_debug(user, Command), morphine_write_debug(user, "\n"), sh(Command). % I should rather use exec(Command, []) here but for % unknown reason, it does not remove the socket file. %------------------------------------------------------------------------------% %:- pred send_message_to_socket(atom). %:- mode send_message_to_socket(in) is det. % low level primitive to send message to the Mercury process via a % socket. send_message_to_socket(Query) :- getval(state_of_morphine, State), ( State == running -> printf(newsock, "%w. \n%b", [Query]), morphine_printf_debug("SEND : +%w. +\n", [Query]) ; State == not_running -> printf(stderr,"No program is running\n", []) ; % State == eot write(stderr,"You are at the end of the trace.\n") ). %------------------------------------------------------------------------------% %:- pred read_message_from_socket(atom). %:- mode read_message_from_socket(out) is det. % low level primitive to read message from the Mercury process via a % socket. read_message_from_socket(Message) :- read(newsock, Message), morphine_printf_debug("RECEIVE : +%w+\n\n", Message). %------------------------------------------------------------------------------% opium_parameter( name : mercury_morphine_socket_address, arg_list : [SocketAdress], arg_type_list : [string], parameter_type : single, default : ["/tmp/"], commands : [], message : "Parameter which gives the directory that will be used to create the temporary \ socket file in (file that is used for socket communication between the two \ process)." ). %------------------------------------------------------------------------------% opium_parameter( name : debug_morphine, arg_list : [OnOff], arg_type_list : [is_member([on, off])], parameter_type : single, default : [off], commands : [morphine_write_debug, morphine_printf_debug], message : 'Prints additional information in the trace to debug Morphine.' ). %------------------------------------------------------------------------------% opium_procedure( name : morphine_write_debug, arg_list : [X], implementation : morphine_write_debug_Op, parameters : [debug_morphine], message : 'Prints additional information to debug Morphine.' ). morphine_write_debug_Op(X) :- (debug_morphine(on) -> write(X) ; true ). opium_procedure( name : morphine_write_debug, arg_list : [Stream, X], implementation : morphine_write_debug_Op, parameters : [debug_morphine], message : 'Prints additional information to debug Morphine.' ). morphine_write_debug_Op(Stream, X) :- (debug_morphine(on) -> write(Stream, X) ; true ), flush(Stream). opium_procedure( name : morphine_printf_debug, arg_list : [Format, X], implementation : morphine_printf_debug_Op, parameters : [debug_morphine], message : 'Prints additional information to debug Morphine.' ). morphine_printf_debug_Op(Format, X) :- (debug_morphine(on) -> printf(Format, X) ; true ). opium_procedure( name : morphine_printf_debug, arg_list : [Stream, Format, X], implementation : morphine_printf_debug_Op, parameters : [debug_morphine], message : 'Prints additional information to debug Morphine.' ). morphine_printf_debug_Op(Stream, Format, X) :- (debug_morphine(on) -> printf(Stream, Format, X) ; true ).