Merge from mainline (gomp-merge-2005-02-26).
[official-gcc.git] / gcc / ada / expect.c
blob3566358a3ddece70263cb0e42c1a383fde26cd01
1 /****************************************************************************
2 * *
3 * GNAT COMPILER COMPONENTS *
4 * *
5 * E X P E C T *
6 * *
7 * C Implementation File *
8 * *
9 * Copyright (C) 2001-2004 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 /* This file provides the low level functionalities needed to implement Expect
47 capabilities in GNAT.Expect.
48 Implementations for unix and windows systems is provided.
49 Dummy stubs are also provided for other systems. */
51 #ifdef _AIX
52 /* Work around the fact that gcc/cpp does not define "__unix__" under AiX. */
53 #define __unix__
54 #endif
56 #ifdef __APPLE__
57 /* Work around the fact that gcc/cpp does not define "__unix__" on Darwin. */
58 #define __unix__
59 #endif
61 #ifdef _WIN32
63 #include <windows.h>
64 #include <process.h>
66 void
67 __gnat_kill (int pid, int sig)
69 HANDLE process_handle;
71 if (sig == 9)
73 process_handle = OpenProcess (PROCESS_TERMINATE, FALSE, pid);
74 if (process_handle != NULL)
75 TerminateProcess (process_handle, 0);
79 int
80 __gnat_expect_fork (void)
82 return 0;
85 void
86 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
88 *pid = (int) spawnve (_P_NOWAIT, cmd, argv, NULL);
91 int
92 __gnat_pipe (int *fd)
94 HANDLE read, write;
96 CreatePipe (&read, &write, NULL, 0);
97 fd[0]=_open_osfhandle ((long)read, 0);
98 fd[1]=_open_osfhandle ((long)write, 0);
99 return 0; /* always success */
103 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
105 #define MAX_DELAY 100
107 int i, delay, infinite = 0;
108 DWORD avail;
109 HANDLE handles[num_fd];
111 for (i = 0; i < num_fd; i++)
112 is_set[i] = 0;
114 for (i = 0; i < num_fd; i++)
115 handles[i] = (HANDLE) _get_osfhandle (fd [i]);
117 /* Start with small delays, and then increase them, to avoid polling too
118 much when waiting a long time */
119 delay = 5;
121 if (timeout < 0)
122 infinite = 1;
124 while (1)
126 for (i = 0; i < num_fd; i++)
128 if (!PeekNamedPipe (handles [i], NULL, 0, NULL, &avail, NULL))
129 return -1;
131 if (avail > 0)
133 is_set[i] = 1;
134 return 1;
138 if (!infinite && timeout <= 0)
139 return 0;
141 Sleep (delay);
142 timeout -= delay;
144 if (delay < MAX_DELAY)
145 delay += 10;
149 #elif defined (VMS)
150 #include <unistd.h>
151 #include <stdio.h>
152 #include <unixio.h>
153 #include <stdlib.h>
154 #include <string.h>
155 #include <descrip.h>
156 #include <stdio.h>
157 #include <stsdef.h>
158 #include <iodef.h>
161 __gnat_pipe (int *fd)
163 return pipe (fd);
167 __gnat_expect_fork (void)
169 return -1;
172 void
173 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
175 *pid = (int) getpid ();
176 /* Since cmd is fully qualified, it is incorrect to call execvp */
177 execv (cmd, argv);
178 _exit (1);
182 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
184 int i, num, ready = 0;
185 unsigned int status;
186 int mbxchans [num_fd];
187 struct dsc$descriptor_s mbxname;
188 struct io_status_block {
189 short int condition;
190 short int count;
191 int dev;
192 } iosb;
193 char buf [256];
195 for (i = 0; i < num_fd; i++)
196 is_set[i] = 0;
198 for (i = 0; i < num_fd; i++)
201 /* Get name of the mailbox used in the pipe */
202 getname (fd [i], buf);
204 /* Assign a channel to the mailbox */
205 if (strlen (buf) > 0)
207 mbxname.dsc$w_length = strlen (buf);
208 mbxname.dsc$b_dtype = DSC$K_DTYPE_T;
209 mbxname.dsc$b_class = DSC$K_CLASS_S;
210 mbxname.dsc$a_pointer = buf;
212 status = SYS$ASSIGN (&mbxname, &mbxchans[i], 0, 0, 0);
214 if ((status & 1) != 1)
216 ready = -1;
217 return ready;
222 num = timeout / 100;
224 while (1)
226 for (i = 0; i < num_fd; i++)
228 if (mbxchans[i] > 0)
231 /* Peek in the mailbox to see if there's data */
232 status = SYS$QIOW
233 (0, mbxchans[i], IO$_SENSEMODE|IO$M_READERCHECK,
234 &iosb, 0, 0, 0, 0, 0, 0, 0, 0);
236 if ((status & 1) != 1)
238 ready = -1;
239 goto deassign;
242 if (iosb.count > 0)
244 is_set[i] = 1;
245 ready = 1;
246 goto deassign;
251 if (timeout > 0 && num == 0)
253 ready = 0;
254 goto deassign;
257 usleep (100000);
258 num--;
261 deassign:
263 /* Deassign channels assigned above */
264 for (i = 0; i < num_fd; i++)
266 if (mbxchans[i] > 0)
267 status = SYS$DASSGN (mbxchans[i]);
270 return ready;
273 #elif defined (__unix__)
275 #ifdef __hpux__
276 #include <sys/ptyio.h>
277 #endif
279 #include <sys/time.h>
281 #ifndef NO_FD_SET
282 #define SELECT_MASK fd_set
283 #else /* !NO_FD_SET */
284 #ifndef _AIX
285 typedef long fd_mask;
286 #endif /* _AIX */
287 #ifdef _IBMR2
288 #define SELECT_MASK void
289 #else /* !_IBMR2 */
290 #define SELECT_MASK int
291 #endif /* !_IBMR2 */
292 #endif /* !NO_FD_SET */
294 void
295 __gnat_kill (int pid, int sig)
297 kill (pid, sig);
301 __gnat_pipe (int *fd)
303 return pipe (fd);
307 __gnat_expect_fork (void)
309 return fork ();
312 void
313 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
315 *pid = (int) getpid ();
316 /* Since cmd is fully qualified, it is incorrect to call execvp */
317 execv (cmd, argv);
318 _exit (1);
322 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
324 struct timeval tv;
325 SELECT_MASK rset;
326 SELECT_MASK eset;
328 int max_fd = 0;
329 int ready;
330 int i;
331 int received;
333 tv.tv_sec = timeout / 1000;
334 tv.tv_usec = (timeout % 1000) * 1000;
336 do {
337 FD_ZERO (&rset);
338 FD_ZERO (&eset);
340 for (i = 0; i < num_fd; i++)
342 FD_SET (fd[i], &rset);
343 FD_SET (fd[i], &eset);
345 if (fd[i] > max_fd)
346 max_fd = fd[i];
349 ready =
350 select (max_fd + 1, &rset, NULL, &eset, timeout == -1 ? NULL : &tv);
352 if (ready > 0)
354 received = 0;
356 for (i = 0; i < num_fd; i++)
358 if (FD_ISSET (fd[i], &rset))
360 is_set[i] = 1;
361 received = 1;
363 else
364 is_set[i] = 0;
367 #ifdef __hpux__
368 for (i = 0; i < num_fd; i++)
370 if (FD_ISSET (fd[i], &eset))
372 struct request_info ei;
374 /* Only query and reset error state if no file descriptor
375 is ready to be read, otherwise we will be signalling a
376 died process too early */
378 if (!received)
380 ioctl (fd[i], TIOCREQCHECK, &ei);
382 if (ei.request == TIOCCLOSE)
384 ioctl (fd[i], TIOCREQSET, &ei);
385 return -1;
388 ioctl (fd[i], TIOCREQSET, &ei);
390 ready--;
393 #endif
395 } while (timeout == -1 && ready == 0);
397 return ready;
400 #else
402 void
403 __gnat_kill (int pid, int sig)
408 __gnat_pipe (int *fd)
410 return -1;
414 __gnat_expect_fork (void)
416 return -1;
419 void
420 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
422 *pid = 0;
426 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
428 return -1;
430 #endif