PR target/4198
[official-gcc.git] / gcc / ada / expect.c
blobdcb6776842e8fd5ad33ea16a6fc802287c1d9b18
1 /****************************************************************************
2 * *
3 * GNAT COMPILER COMPONENTS *
4 * *
5 * E X P E C T *
6 * *
7 * C Implementation File *
8 * *
9 * Copyright (C) 2001-2005 Ada Core Technologies, Inc. *
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 2, 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. See the GNU General Public License *
17 * for more details. You should have received a copy of the GNU General *
18 * Public License distributed with GNAT; see file COPYING. If not, write *
19 * to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, *
20 * MA 02111-1307, USA. *
21 * *
22 * As a special exception, if you link this file with other files to *
23 * produce an executable, this file does not by itself cause the resulting *
24 * executable to be covered by the GNU General Public License. This except- *
25 * ion does not however invalidate any other reasons why the executable *
26 * file might be covered by the GNU Public License. *
27 * *
28 * GNAT was originally developed by the GNAT team at New York University. *
29 * Extensive contributions were provided by Ada Core Technologies Inc. *
30 * *
31 ****************************************************************************/
33 #ifdef __alpha_vxworks
34 #include "vxWorks.h"
35 #endif
37 #ifdef IN_RTS
38 #define POSIX
39 #include "tconfig.h"
40 #include "tsystem.h"
41 #else
42 #include "config.h"
43 #include "system.h"
44 #endif
46 #include <sys/types.h>
48 #ifdef __MINGW32__
49 #if OLD_MINGW
50 #include <sys/wait.h>
51 #endif
52 #else
53 #include <sys/wait.h>
54 #endif
56 /* This file provides the low level functionalities needed to implement Expect
57 capabilities in GNAT.Expect.
58 Implementations for unix and windows systems is provided.
59 Dummy stubs are also provided for other systems. */
61 #ifdef _AIX
62 /* Work around the fact that gcc/cpp does not define "__unix__" under AiX. */
63 #define __unix__
64 #endif
66 #ifdef __APPLE__
67 /* Work around the fact that gcc/cpp does not define "__unix__" on Darwin. */
68 #define __unix__
69 #endif
71 #ifdef _WIN32
73 #include <windows.h>
74 #include <process.h>
76 void
77 __gnat_kill (int pid, int sig)
79 HANDLE process_handle;
81 if (sig == 9)
83 process_handle = OpenProcess (PROCESS_TERMINATE, FALSE, pid);
84 if (process_handle != NULL)
86 TerminateProcess (process_handle, 0);
87 CloseHandle (process_handle);
92 int
93 __gnat_waitpid (int pid)
95 HANDLE process_handle;
96 DWORD exitcode = 1;
97 DWORD res;
99 process_handle = OpenProcess (PROCESS_QUERY_INFORMATION, FALSE, pid);
101 if (process_handle != NULL)
103 res = WaitForSingleObject (process_handle, INFINITE);
104 GetExitCodeProcess (process_handle, &exitcode);
105 CloseHandle (process_handle);
108 return (int) exitcode;
112 __gnat_expect_fork (void)
114 return 0;
117 void
118 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
120 *pid = (int) spawnve (_P_NOWAIT, cmd, argv, NULL);
124 __gnat_pipe (int *fd)
126 HANDLE read, write;
128 CreatePipe (&read, &write, NULL, 0);
129 fd[0]=_open_osfhandle ((long)read, 0);
130 fd[1]=_open_osfhandle ((long)write, 0);
131 return 0; /* always success */
135 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
137 #define MAX_DELAY 100
139 int i, delay, infinite = 0;
140 DWORD avail;
141 HANDLE handles[num_fd];
143 for (i = 0; i < num_fd; i++)
144 is_set[i] = 0;
146 for (i = 0; i < num_fd; i++)
147 handles[i] = (HANDLE) _get_osfhandle (fd [i]);
149 /* Start with small delays, and then increase them, to avoid polling too
150 much when waiting a long time */
151 delay = 5;
153 if (timeout < 0)
154 infinite = 1;
156 while (1)
158 for (i = 0; i < num_fd; i++)
160 if (!PeekNamedPipe (handles [i], NULL, 0, NULL, &avail, NULL))
161 return -1;
163 if (avail > 0)
165 is_set[i] = 1;
166 return 1;
170 if (!infinite && timeout <= 0)
171 return 0;
173 Sleep (delay);
174 timeout -= delay;
176 if (delay < MAX_DELAY)
177 delay += 10;
181 #elif defined (VMS)
182 #include <unistd.h>
183 #include <stdio.h>
184 #include <unixio.h>
185 #include <stdlib.h>
186 #include <string.h>
187 #include <vms/descrip.h>
188 #include <stdio.h>
189 #include <vms/stsdef.h>
190 #include <vms/iodef.h>
193 __gnat_waitpid (int pid)
195 int status = 0;
197 waitpid (pid, &status, 0);
198 status = WEXITSTATUS (status);
200 return status;
204 __gnat_pipe (int *fd)
206 return pipe (fd);
210 __gnat_expect_fork (void)
212 return -1;
215 void
216 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
218 *pid = (int) getpid ();
219 /* Since cmd is fully qualified, it is incorrect to call execvp */
220 execv (cmd, argv);
221 _exit (1);
225 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
227 int i, num, ready = 0;
228 unsigned int status;
229 int mbxchans [num_fd];
230 struct dsc$descriptor_s mbxname;
231 struct io_status_block {
232 short int condition;
233 short int count;
234 int dev;
235 } iosb;
236 char buf [256];
238 for (i = 0; i < num_fd; i++)
239 is_set[i] = 0;
241 for (i = 0; i < num_fd; i++)
244 /* Get name of the mailbox used in the pipe */
245 getname (fd [i], buf);
247 /* Assign a channel to the mailbox */
248 if (strlen (buf) > 0)
250 mbxname.dsc$w_length = strlen (buf);
251 mbxname.dsc$b_dtype = DSC$K_DTYPE_T;
252 mbxname.dsc$b_class = DSC$K_CLASS_S;
253 mbxname.dsc$a_pointer = buf;
255 status = SYS$ASSIGN (&mbxname, &mbxchans[i], 0, 0, 0);
257 if ((status & 1) != 1)
259 ready = -1;
260 return ready;
265 num = timeout / 100;
267 while (1)
269 for (i = 0; i < num_fd; i++)
271 if (mbxchans[i] > 0)
274 /* Peek in the mailbox to see if there's data */
275 status = SYS$QIOW
276 (0, mbxchans[i], IO$_SENSEMODE|IO$M_READERCHECK,
277 &iosb, 0, 0, 0, 0, 0, 0, 0, 0);
279 if ((status & 1) != 1)
281 ready = -1;
282 goto deassign;
285 if (iosb.count > 0)
287 is_set[i] = 1;
288 ready = 1;
289 goto deassign;
294 if (timeout > 0 && num == 0)
296 ready = 0;
297 goto deassign;
300 usleep (100000);
301 num--;
304 deassign:
306 /* Deassign channels assigned above */
307 for (i = 0; i < num_fd; i++)
309 if (mbxchans[i] > 0)
310 status = SYS$DASSGN (mbxchans[i]);
313 return ready;
316 #elif defined (__unix__)
318 #ifdef __hpux__
319 #include <sys/ptyio.h>
320 #endif
322 #include <sys/time.h>
324 #ifndef NO_FD_SET
325 #define SELECT_MASK fd_set
326 #else /* !NO_FD_SET */
327 #ifndef _AIX
328 typedef long fd_mask;
329 #endif /* _AIX */
330 #ifdef _IBMR2
331 #define SELECT_MASK void
332 #else /* !_IBMR2 */
333 #define SELECT_MASK int
334 #endif /* !_IBMR2 */
335 #endif /* !NO_FD_SET */
337 void
338 __gnat_kill (int pid, int sig)
340 kill (pid, sig);
344 __gnat_waitpid (int pid)
346 int status = 0;
348 waitpid (pid, &status, 0);
349 status = WEXITSTATUS (status);
351 return status;
355 __gnat_pipe (int *fd)
357 return pipe (fd);
361 __gnat_expect_fork (void)
363 return fork ();
366 void
367 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
369 *pid = (int) getpid ();
370 /* Since cmd is fully qualified, it is incorrect to call execvp */
371 execv (cmd, argv);
372 _exit (1);
376 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
378 struct timeval tv;
379 SELECT_MASK rset;
380 SELECT_MASK eset;
382 int max_fd = 0;
383 int ready;
384 int i;
385 int received;
387 tv.tv_sec = timeout / 1000;
388 tv.tv_usec = (timeout % 1000) * 1000;
390 do {
391 FD_ZERO (&rset);
392 FD_ZERO (&eset);
394 for (i = 0; i < num_fd; i++)
396 FD_SET (fd[i], &rset);
397 FD_SET (fd[i], &eset);
399 if (fd[i] > max_fd)
400 max_fd = fd[i];
403 ready =
404 select (max_fd + 1, &rset, NULL, &eset, timeout == -1 ? NULL : &tv);
406 if (ready > 0)
408 received = 0;
410 for (i = 0; i < num_fd; i++)
412 if (FD_ISSET (fd[i], &rset))
414 is_set[i] = 1;
415 received = 1;
417 else
418 is_set[i] = 0;
421 #ifdef __hpux__
422 for (i = 0; i < num_fd; i++)
424 if (FD_ISSET (fd[i], &eset))
426 struct request_info ei;
428 /* Only query and reset error state if no file descriptor
429 is ready to be read, otherwise we will be signalling a
430 died process too early */
432 if (!received)
434 ioctl (fd[i], TIOCREQCHECK, &ei);
436 if (ei.request == TIOCCLOSE)
438 ioctl (fd[i], TIOCREQSET, &ei);
439 return -1;
442 ioctl (fd[i], TIOCREQSET, &ei);
444 ready--;
447 #endif
449 } while (timeout == -1 && ready == 0);
451 return ready;
454 #else
456 void
457 __gnat_kill (int pid, int sig)
462 __gnat_waitpid (int pid, int sig)
464 return 0;
468 __gnat_pipe (int *fd)
470 return -1;
474 __gnat_expect_fork (void)
476 return -1;
479 void
480 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
482 *pid = 0;
486 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
488 return -1;
490 #endif