Implement -mmemcpy-strategy= and -mmemset-strategy= options
[official-gcc.git] / gcc / ada / g-exptty.adb
blob7ec04727d072504c474329926a3c924bab73d0c4
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT LIBRARY COMPONENTS --
4 -- --
5 -- G N A T . E X P E C T . T T Y --
6 -- --
7 -- S p e c --
8 -- --
9 -- Copyright (C) 2000-2011, AdaCore --
10 -- --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. --
17 -- --
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
19 -- additional permissions described in the GCC Runtime Library Exception, --
20 -- version 3.1, as published by the Free Software Foundation. --
21 -- --
22 -- You should have received a copy of the GNU General Public License and --
23 -- a copy of the GCC Runtime Library Exception along with this program; --
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
25 -- <http://www.gnu.org/licenses/>. --
26 -- --
27 -- GNAT was originally developed by the GNAT team at New York University. --
28 -- Extensive contributions were provided by Ada Core Technologies Inc. --
29 -- --
30 ------------------------------------------------------------------------------
32 with GNAT.OS_Lib; use GNAT.OS_Lib;
34 with System; use System;
36 package body GNAT.Expect.TTY is
38 On_Windows : constant Boolean := Directory_Separator = '\';
39 -- True when on Windows
41 -----------
42 -- Close --
43 -----------
45 overriding procedure Close
46 (Descriptor : in out TTY_Process_Descriptor;
47 Status : out Integer)
49 procedure Terminate_Process (Process : System.Address);
50 pragma Import (C, Terminate_Process, "__gnat_terminate_process");
52 function Waitpid (Process : System.Address) return Integer;
53 pragma Import (C, Waitpid, "__gnat_waitpid");
54 -- Wait for a specific process id, and return its exit code
56 procedure Free_Process (Process : System.Address);
57 pragma Import (C, Free_Process, "__gnat_free_process");
59 procedure Close_TTY (Process : System.Address);
60 pragma Import (C, Close_TTY, "__gnat_close_tty");
62 begin
63 -- If we haven't already closed the process
65 if Descriptor.Process = System.Null_Address then
66 Status := -1;
68 else
69 if Descriptor.Input_Fd /= Invalid_FD then
70 Close (Descriptor.Input_Fd);
71 end if;
73 if Descriptor.Error_Fd /= Descriptor.Output_Fd
74 and then Descriptor.Error_Fd /= Invalid_FD
75 then
76 Close (Descriptor.Error_Fd);
77 end if;
79 if Descriptor.Output_Fd /= Invalid_FD then
80 Close (Descriptor.Output_Fd);
81 end if;
83 -- Send a Ctrl-C to the process first. This way, if the
84 -- launched process is a "sh" or "cmd", the child processes
85 -- will get terminated as well. Otherwise, terminating the
86 -- main process brutally will leave the children running.
88 Interrupt (Descriptor);
89 delay 0.05;
91 Terminate_Process (Descriptor.Process);
92 Status := Waitpid (Descriptor.Process);
94 if not On_Windows then
95 Close_TTY (Descriptor.Process);
96 end if;
98 Free_Process (Descriptor.Process'Address);
99 Descriptor.Process := System.Null_Address;
101 GNAT.OS_Lib.Free (Descriptor.Buffer);
102 Descriptor.Buffer_Size := 0;
103 end if;
104 end Close;
106 overriding procedure Close (Descriptor : in out TTY_Process_Descriptor) is
107 Status : Integer;
108 begin
109 Close (Descriptor, Status);
110 end Close;
112 -----------------------------
113 -- Close_Pseudo_Descriptor --
114 -----------------------------
116 procedure Close_Pseudo_Descriptor
117 (Descriptor : in out TTY_Process_Descriptor)
119 begin
120 Descriptor.Buffer_Size := 0;
121 GNAT.OS_Lib.Free (Descriptor.Buffer);
122 end Close_Pseudo_Descriptor;
124 ---------------
125 -- Interrupt --
126 ---------------
128 overriding procedure Interrupt
129 (Descriptor : in out TTY_Process_Descriptor)
131 procedure Internal (Process : System.Address);
132 pragma Import (C, Internal, "__gnat_interrupt_process");
133 begin
134 if Descriptor.Process /= System.Null_Address then
135 Internal (Descriptor.Process);
136 end if;
137 end Interrupt;
139 procedure Interrupt (Pid : Integer) is
140 procedure Internal (Pid : Integer);
141 pragma Import (C, Internal, "__gnat_interrupt_pid");
142 begin
143 Internal (Pid);
144 end Interrupt;
146 -----------------------
147 -- Pseudo_Descriptor --
148 -----------------------
150 procedure Pseudo_Descriptor
151 (Descriptor : out TTY_Process_Descriptor'Class;
152 TTY : GNAT.TTY.TTY_Handle;
153 Buffer_Size : Natural := 4096) is
154 begin
155 Descriptor.Input_Fd := GNAT.TTY.TTY_Descriptor (TTY);
156 Descriptor.Output_Fd := Descriptor.Input_Fd;
158 -- Create the buffer
160 Descriptor.Buffer_Size := Buffer_Size;
162 if Buffer_Size /= 0 then
163 Descriptor.Buffer := new String (1 .. Positive (Buffer_Size));
164 end if;
165 end Pseudo_Descriptor;
167 ----------
168 -- Send --
169 ----------
171 overriding procedure Send
172 (Descriptor : in out TTY_Process_Descriptor;
173 Str : String;
174 Add_LF : Boolean := True;
175 Empty_Buffer : Boolean := False)
177 Header : String (1 .. 5);
178 Length : Natural;
179 Ret : Natural;
181 procedure Internal
182 (Process : System.Address;
183 S : in out String;
184 Length : Natural;
185 Ret : out Natural);
186 pragma Import (C, Internal, "__gnat_send_header");
188 begin
189 Length := Str'Length;
191 if Add_LF then
192 Length := Length + 1;
193 end if;
195 Internal (Descriptor.Process, Header, Length, Ret);
197 if Ret = 1 then
199 -- Need to use the header
201 GNAT.Expect.Send
202 (Process_Descriptor (Descriptor),
203 Header & Str, Add_LF, Empty_Buffer);
205 else
206 GNAT.Expect.Send
207 (Process_Descriptor (Descriptor),
208 Str, Add_LF, Empty_Buffer);
209 end if;
210 end Send;
212 --------------
213 -- Set_Size --
214 --------------
216 procedure Set_Size
217 (Descriptor : in out TTY_Process_Descriptor'Class;
218 Rows : Natural;
219 Columns : Natural)
221 procedure Internal (Process : System.Address; R, C : Integer);
222 pragma Import (C, Internal, "__gnat_setup_winsize");
223 begin
224 if Descriptor.Process /= System.Null_Address then
225 Internal (Descriptor.Process, Rows, Columns);
226 end if;
227 end Set_Size;
229 ---------------------------
230 -- Set_Up_Communications --
231 ---------------------------
233 overriding procedure Set_Up_Communications
234 (Pid : in out TTY_Process_Descriptor;
235 Err_To_Out : Boolean;
236 Pipe1 : access Pipe_Type;
237 Pipe2 : access Pipe_Type;
238 Pipe3 : access Pipe_Type)
240 pragma Unreferenced (Err_To_Out, Pipe1, Pipe2, Pipe3);
242 function Internal (Process : System.Address) return Integer;
243 pragma Import (C, Internal, "__gnat_setup_communication");
245 begin
246 if Internal (Pid.Process'Address) /= 0 then
247 raise Invalid_Process with "cannot setup communication.";
248 end if;
249 end Set_Up_Communications;
251 ---------------------------------
252 -- Set_Up_Child_Communications --
253 ---------------------------------
255 overriding procedure Set_Up_Child_Communications
256 (Pid : in out TTY_Process_Descriptor;
257 Pipe1 : in out Pipe_Type;
258 Pipe2 : in out Pipe_Type;
259 Pipe3 : in out Pipe_Type;
260 Cmd : String;
261 Args : System.Address)
263 pragma Unreferenced (Pipe1, Pipe2, Pipe3, Cmd);
264 function Internal
265 (Process : System.Address; Argv : System.Address; Use_Pipes : Integer)
266 return Process_Id;
267 pragma Import (C, Internal, "__gnat_setup_child_communication");
269 begin
270 Pid.Pid := Internal (Pid.Process, Args, Boolean'Pos (Pid.Use_Pipes));
271 end Set_Up_Child_Communications;
273 ----------------------------------
274 -- Set_Up_Parent_Communications --
275 ----------------------------------
277 overriding procedure Set_Up_Parent_Communications
278 (Pid : in out TTY_Process_Descriptor;
279 Pipe1 : in out Pipe_Type;
280 Pipe2 : in out Pipe_Type;
281 Pipe3 : in out Pipe_Type)
283 pragma Unreferenced (Pipe1, Pipe2, Pipe3);
285 procedure Internal
286 (Process : System.Address;
287 Inputfp : out File_Descriptor;
288 Outputfp : out File_Descriptor;
289 Errorfp : out File_Descriptor;
290 Pid : out Process_Id);
291 pragma Import (C, Internal, "__gnat_setup_parent_communication");
293 begin
294 Internal
295 (Pid.Process, Pid.Input_Fd, Pid.Output_Fd, Pid.Error_Fd, Pid.Pid);
296 end Set_Up_Parent_Communications;
298 -------------------
299 -- Set_Use_Pipes --
300 -------------------
302 procedure Set_Use_Pipes
303 (Descriptor : in out TTY_Process_Descriptor;
304 Use_Pipes : Boolean) is
305 begin
306 Descriptor.Use_Pipes := Use_Pipes;
307 end Set_Use_Pipes;
309 end GNAT.Expect.TTY;