stdlib/strings: Moved Buffer to FlatBuffer, Buffer is now abstract.
[nit.git] / src / dbgcli.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2013 Lucas Bajolet <lucas.bajolet@gmail.com>
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 # Client for the nit debugger nitdbg
18 #
19 # Can send commands to the debugger
20 module dbgcli
21
22 import socket
23 import toolcontext
24
25 redef class ToolContext
26
27 var opt_host_address: OptionString = new OptionString("Sets the host to debug from, use IPV4 only (Defaults to 127.0.0.1)", "--host")
28 var opt_debug_port: OptionInt = new OptionInt("Sets the debug port (Defaults to 22125) - Must be contained between 0 and 65535", 22125, "--port")
29
30 redef init
31 do
32 super
33 self.option_context.add_option(self.opt_host_address)
34 self.option_context.add_option(self.opt_debug_port)
35 end
36
37 end
38
39 redef class String
40
41 # Checks if the actual string is a valid IPv4 address
42 # That is, if the pattern is int.int.int.int where each int must be between 0 and 255
43 fun is_valid_ipv4_address: Bool
44 do
45 var components = self.split_with(".")
46 if components.length != 4 then return false
47 for i in components do
48 if not i.is_numeric or not (i.to_i <= 255 and i.to_i >= 0) then return false
49 end
50 return true
51 end
52
53 end
54
55 # Persistant connection to the debugger
56 # Default port = 22125
57 #
58 class DebugClient
59
60 var debugger_connection: Socket
61
62 init (host: String, port: Int)
63 do
64 self.debugger_connection = new Socket.stream_with_host(host, port)
65 print "[HOST ADDRESS] : "+debugger_connection.address
66 print "[HOST] : "+debugger_connection.host.as(not null)
67 print "[PORT] : "+debugger_connection.port.to_s
68 print "Connecting ... "+debugger_connection.connect.to_s
69 end
70
71 init with_port (host: String, port: Int)
72 do
73 debugger_connection = new Socket.stream_with_host(host, port)
74 end
75
76 fun send_command(command: String)
77 do
78 debugger_connection.write(command+"\n")
79 end
80
81 fun connected: Bool
82 do
83 return self.debugger_connection.connected
84 end
85
86 fun ready: Bool
87 do
88 return debugger_connection.ready_to_read(40)
89 end
90
91 fun read_command: String
92 do
93 var buff = new FlatBuffer
94 while debugger_connection.ready_to_read(40) do buff.append(debugger_connection.read)
95 return buff.to_s
96 end
97
98 fun disconnect
99 do
100 debugger_connection.close
101 end
102
103 end
104
105 # Create a tool context to handle options and paths
106 var toolcontext = new ToolContext
107 toolcontext.process_options
108
109 var debug: DebugClient
110
111 if toolcontext.opt_help.value then
112 toolcontext.option_context.usage
113 return
114 end
115
116 # If the port value is not an Int between 0 and 65535 (Mandatory according to the norm)
117 # Print the usage
118 if toolcontext.opt_debug_port.value < 0 or toolcontext.opt_debug_port.value > 65535 then
119 toolcontext.option_context.usage
120 return
121 end
122
123 # An IPV4 address does always complies to this form : x.x.x.x
124 # Where x is an integer whose value is >=0 and <= 255
125 if toolcontext.opt_host_address.value != null then
126 if toolcontext.opt_host_address.value.is_valid_ipv4_address then
127 debug = new DebugClient(toolcontext.opt_host_address.value.as(not null), toolcontext.opt_debug_port.value)
128 else
129 toolcontext.option_context.usage
130 return
131 end
132 else
133 debug = new DebugClient("127.0.0.1", toolcontext.opt_debug_port.value)
134 end
135
136 var recv_cmd: String
137
138 var written_cmd: String
139
140 var over = false
141
142 while not over do
143 if stdin.poll_in then
144 written_cmd = gets
145 debug.send_command(written_cmd)
146 if written_cmd == "kill" then
147 over = true
148 end
149 end
150
151 if not over and debug.ready then
152 recv_cmd = debug.read_command
153 var command_parts = recv_cmd.split("\n")
154 for i in command_parts do
155 if i == "DBG DONE WORK ON SELF" then
156 debug.send_command("CLIENT DBG DONE ACK")
157 over = true
158 end
159 print i
160 end
161 end
162 end
163
164 debug.disconnect