1% ----------------------------------------------------------------------
2% BEGIN LICENSE BLOCK
3% Version: CMPL 1.1
4%
5% The contents of this file are subject to the Cisco-style Mozilla Public
6% License Version 1.1 (the "License"); you may not use this file except
7% in compliance with the License.  You may obtain a copy of the License
8% at www.eclipse-clp.org/license.
9%
10% Software distributed under the License is distributed on an "AS IS"
11% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See
12% the License for the specific language governing rights and limitations
13% under the License.
14%
15% The Original Code is  The ECLiPSe Constraint Logic Programming System.
16% The Initial Developer of the Original Code is  Cisco Systems, Inc.
17% Portions created by the Initial Developer are
18% Copyright (C) 1999-2006 Cisco Systems, Inc.  All Rights Reserved.
19%
20% Contributor(s): IC-Parc, Imperal College London
21%
22% END LICENSE BLOCK
23%
24%
25% ECLiPSe II remote development tools ECLiPSe side interface
26%
27% System:	ECLiPSe Constraint Logic Programming System
28% Version:	$Id: remote_tools.pl,v 1.4 2015/01/14 01:31:09 jschimpf Exp $
29% Authors:	Kish Shen, IC-Parc
30%
31%----------------------------------------------------------------------
32:- module(remote_tools).
33:- pragma(system).
34:- lib(tracer_tcl).
35
36
37:- local variable(control_stream).
38:- untraceable tools/0, attach_tools/0,attached/1.
39:- export attach_tools/0, attach_tools/3, tools/0, attached/1.
40
41:- tool(attach_tools/3, attach_tools/4).
42
43:- import set_default_error_handler/2 from sepia_kernel.
44
45
46attach_tools :-
47	\+attached(_),
48	install_guitools,
49	remote_connect(_A, ControlStream, post_attach(ControlStream)).
50
51attach_tools(Address, Block, Goal, Module) :-
52	\+attached(_),
53	install_guitools,
54	remote_connect_setup(Address, Con, Soc),
55	catch(
56	   (call(Goal)@Module,
57	    remote_connect_accept(Con, Soc, Block, post_attach(Con), "", _) ->
58		true
59	   ;
60		current_stream(Soc), close(Soc), fail
61	   ), Tag,
62	   ((current_stream(Soc) -> close(Soc) ; true),
63	    throw(Tag)
64	   )
65	).
66
67
68post_attach(ControlStream) :-
69	set_event_handler(ControlStream, disconnect_handler/0),
70	setval(control_stream, ControlStream).
71
72
73attached(ControlStream) :-
74	getval(control_stream, ControlStream),
75	nonvar(ControlStream).
76
77tools :-
78	(attached(ControlStream) ->
79	    true
80	;
81	    % not yet attached, try to launch
82	    printf(log_output, "Launching Tktools...%n%b", []),
83	    attach_tools(HostPort, 10, launch_tools(HostPort)),
84	    attached(ControlStream),
85	    printf(log_output, "TkTools started on %w%n%b", [HostPort])
86	),
87	catch(remote_yield(ControlStream), abort,
88	   (writeln(log_output, "Disconnected from remote tools"),
89	    throw(abort)
90	   )
91	).
92
93launch_tools(Host/Port) :-
94	get_flag(installation_directory, EclipseDir),
95	get_flag(hostarch, Arch),
96	( substring(Arch, _, 3, 0, "_nt") ->
97
98	    join_string([EclipseDir,tcltk,Arch,bin,"wish85.exe"], /, Wish),
99	    join_string([EclipseDir,lib_tcl,"tktools.tcl"], /, TkTools),
100	    os_file_name(TkTools, TkToolsOS),
101	    Command = [Wish,TkToolsOS,--,'-h',Host,'-p',Port]
102
103	;
104	    join_string([EclipseDir,bin,Arch,tktools], /, TkTools),
105	    Command = [TkTools,'-h',Host,'-p',Port]
106	),
107	exec_group(Command, [], _Pid).
108
109disconnect_handler :-
110	uninstall_guitools,
111	open(queue(""), read, debug_input), % just create a dummy queue
112	setval(control_stream, _),
113	erase_module(tracer_tcl).
114
115:- skipped tools/0, attach_tools/0.
116
117%----------------------------------------------------
118:- comment(categories, ["Development Tools"]).
119:- comment(summary, "Allow the Tk development tools to be used remotely").
120
121:- comment(desc,
122"This library allows the Tk development tools to be used via the remote Tcl
123interface. This allows the development tools to be used by any ECLiPSe
124session, and not just one which uses the embedded Tcl interface.").
125
126
127:- comment(tools/0, [
128summary: "Transfer control from ECLiPSe to the development tools.",
129desc: html("\
130<P>
131	Transfer the `control' from ECLiPSe to the development tools,
132	allowing the user to use the development tools GUI interactively.
133	This predicate returns when control is returned to ECLiPSe.
134<P>
135        Note that some features of the development tools can be triggered
136        without interacting directly with the GUI. For example, placing a
137        spy-point on a predicate will cause the tracer tool to pop-up when
138        the predicate is called.
139<P>
140        If the development tools have not been attached beforehand,
141	the predicate tries to start them on the local machine,
142	and attaches them.
143"),
144see_also: [attach_tools/0,attach_tools/3],
145resat: no
146]).
147
148:- comment(attach_tools/0, [
149summary: "Initiate the attachment of remote development tools",
150desc:   html("\
151   <P>Initiate the attachment of the remote development tools. This will create
152   a connection waiting for the remote development tools to be attached to.
153   It will print the hostname and the port number that should be given to
154   the development tools. The remote development tools should be started
155   and supplied with the hostname and port number. Once this is done, the
156   development tools are ready to be used. Control is initially given back
157   to ECLiPSe when the tools have been attached."),
158resat: no,
159fail_if: "Development tools already attached.",
160see_also: [tools/0, attach_tools/3]
161]).
162
163:- comment(attach_tools/3, [
164summary: "A flexible attachment of remote development tools",
165amode: attach_tools(?,++,?),
166args: ["Address":  "Address for the remote connection (Host/Port or variable)",
167       "TimeOut":  "Time-out interval (int/float or the atom block)",
168       "Goal"   :  "Goal to execute during connection"
169      ],
170desc:   html("\
171
172   <P>Initiate the attachment of the remote development tools, providing the
173   user with more control over the connection than attach_tools/0. The
174   predicate will create a connection waiting for the remote development
175   tools to be attached to.  It will then execute Goal and then tries to
176   complete the connection by waiting at most TimeOut seconds for the
177   remote development tools to connect.  If TimeOut is the atom block, then
178   it will wait indefinitely.
179
180   </P><P>Address is the Host/Port address that the remote connection will be
181   made.  This can be left as a variable, so that the system can determine
182   its own address, or the user can specify a specific Port. The main
183   purpose for Goal is to allow the user to start out the remote
184   development tools from it using Address, so that the user does not need
185   to manually connect the remote development tools. Control is initially
186   given back to ECLiPSe when the tools have been attached.
187
188   </P><P>The predicate will fail or throw an exception if Goal respectively fails
189   or throw an exception. It will also fail if it waits more than TimeOut
190   seconds for the remote tools to connect. In these cases, the server
191   socket will be properly closed.
192
193   </P><P>attach_tools/0 can be implemented using attach_tools/3 as follows:
194
195   <PRE>
196         attach_tools :-
197             attach_tools(_, block, true).
198   </PRE>
199   "),
200eg: "
201    % the following will cause the remote tools to start automatically
202    % if tktools can be run from a shell. It will wait 10 seconds before
203    % failing and closing the server socket.
204    [eclipse 2]:  attach_tools(H/P,10,
205         exec(['tktools','--','-h',H,'-p',P], [], Pid)).
206
207    H = 'cow.icparc.ic.ac.uk'
208    P = 1953
209    Pid = 27678
210    Yes (0.04s cpu)
211    [eclipse 3]:
212   ",
213resat: no,
214exceptions: [
215    4: "Goal or TimeOut are variables",
216    5: "TimeOut is not an integer nor float nor atom",
217    6: "TimeOut is either too small or large or is an atom other than block"
218   ],
219fail_if: "   Development tools already attached, or waiting TimeOut seconds
220   for remote tools to connect, or if Goal fails",
221see_also: [tools/0, attach_tools/0]
222]).
223
224:- comment(attached/1, [
225summary: "Checks if remote tools are currently attached or not.",
226amode: attached(?),
227args: ["ControlStream": "control stream (stream name or variable)"],
228fail_if: "Remote tools are not currently attached.",
229desc: html("\
230<P>
231	Checks if the remote development tools have been attached to this
232        ECLiPSe session or not. If attached, the predicate succeeds and
233        returns the stream name of the control stream. If not attached, the
234        predicate fails."
235)]).
236
237
238
239
240
241