2003-12-26 Guilhem Lavaux <guilhem@kaffe.org>
[official-gcc.git] / gcc / ada / expect.c
blob54952268517a9d27ae8d815310065cc90ed7c49a
1 /****************************************************************************
2 * *
3 * GNAT COMPILER COMPONENTS *
4 * *
5 * E X P E C T *
6 * *
7 * C Implementation File *
8 * *
9 * Copyright (C) 2001-2003 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 _WIN32
58 #include <windows.h>
59 #include <process.h>
61 void
62 __gnat_kill (int pid, int sig)
64 HANDLE process_handle;
66 if (sig == 9)
68 process_handle = OpenProcess (PROCESS_TERMINATE, FALSE, pid);
69 if (process_handle != NULL)
70 TerminateProcess (process_handle, 0);
74 int
75 __gnat_expect_fork (void)
77 return 0;
80 void
81 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
83 *pid = (int) spawnve (_P_NOWAIT, cmd, argv, NULL);
86 int
87 __gnat_pipe (int *fd)
89 HANDLE read, write;
91 CreatePipe (&read, &write, NULL, 0);
92 fd[0]=_open_osfhandle ((long)read, 0);
93 fd[1]=_open_osfhandle ((long)write, 0);
94 return 0; /* always success */
97 int
98 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
100 #define MAX_DELAY 100
102 int i, delay, infinite = 0;
103 DWORD avail;
104 HANDLE handles[num_fd];
106 for (i = 0; i < num_fd; i++)
107 is_set[i] = 0;
109 for (i = 0; i < num_fd; i++)
110 handles[i] = (HANDLE) _get_osfhandle (fd [i]);
112 /* Start with small delays, and then increase them, to avoid polling too
113 much when waiting a long time */
114 delay = 5;
116 if (timeout < 0)
117 infinite = 1;
119 while (1)
121 for (i = 0; i < num_fd; i++)
123 if (!PeekNamedPipe (handles [i], NULL, 0, NULL, &avail, NULL))
124 return -1;
126 if (avail > 0)
128 is_set[i] = 1;
129 return 1;
133 if (!infinite && timeout <= 0)
134 return 0;
136 Sleep (delay);
137 timeout -= delay;
139 if (delay < MAX_DELAY)
140 delay += 10;
144 #elif defined (VMS)
145 #include <unistd.h>
146 #include <stdio.h>
147 #include <unixio.h>
148 #include <stdlib.h>
149 #include <string.h>
150 #include <descrip.h>
151 #include <stdio.h>
152 #include <stsdef.h>
153 #include <iodef.h>
156 __gnat_pipe (int *fd)
158 return pipe (fd);
162 __gnat_expect_fork (void)
164 return -1;
167 void
168 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
170 *pid = (int) getpid ();
171 /* Since cmd is fully qualified, it is incorrect to call execvp */
172 execv (cmd, argv);
173 _exit (1);
177 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
179 int i, num, ready = 0;
180 unsigned int status;
181 int mbxchans [num_fd];
182 struct dsc$descriptor_s mbxname;
183 struct io_status_block {
184 short int condition;
185 short int count;
186 int dev;
187 } iosb;
188 char buf [256];
190 for (i = 0; i < num_fd; i++)
191 is_set[i] = 0;
193 for (i = 0; i < num_fd; i++)
196 /* Get name of the mailbox used in the pipe */
197 getname (fd [i], buf);
199 /* Assign a channel to the mailbox */
200 if (strlen (buf) > 0)
202 mbxname.dsc$w_length = strlen (buf);
203 mbxname.dsc$b_dtype = DSC$K_DTYPE_T;
204 mbxname.dsc$b_class = DSC$K_CLASS_S;
205 mbxname.dsc$a_pointer = buf;
207 status = SYS$ASSIGN (&mbxname, &mbxchans[i], 0, 0, 0);
209 if ((status & 1) != 1)
211 ready = -1;
212 return ready;
217 num = timeout / 100;
219 while (1)
221 for (i = 0; i < num_fd; i++)
223 if (mbxchans[i] > 0)
226 /* Peek in the mailbox to see if there's data */
227 status = SYS$QIOW
228 (0, mbxchans[i], IO$_SENSEMODE|IO$M_READERCHECK,
229 &iosb, 0, 0, 0, 0, 0, 0, 0, 0);
231 if ((status & 1) != 1)
233 ready = -1;
234 goto deassign;
237 if (iosb.count > 0)
239 is_set[i] = 1;
240 ready = 1;
241 goto deassign;
246 if (timeout > 0 && num == 0)
248 ready = 0;
249 goto deassign;
252 usleep (100000);
253 num--;
256 deassign:
258 /* Deassign channels assigned above */
259 for (i = 0; i < num_fd; i++)
261 if (mbxchans[i] > 0)
262 status = SYS$DASSGN (mbxchans[i]);
265 return ready;
268 #elif defined (unix)
270 #ifdef hpux
271 #include <sys/ptyio.h>
272 #endif
274 #include <sys/time.h>
276 #ifndef NO_FD_SET
277 #define SELECT_MASK fd_set
278 #else /* !NO_FD_SET */
279 #ifndef _AIX
280 typedef long fd_mask;
281 #endif /* _AIX */
282 #ifdef _IBMR2
283 #define SELECT_MASK void
284 #else /* !_IBMR2 */
285 #define SELECT_MASK int
286 #endif /* !_IBMR2 */
287 #endif /* !NO_FD_SET */
289 void
290 __gnat_kill (int pid, int sig)
292 kill (pid, sig);
296 __gnat_pipe (int *fd)
298 return pipe (fd);
302 __gnat_expect_fork (void)
304 return fork ();
307 void
308 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
310 *pid = (int) getpid ();
311 /* Since cmd is fully qualified, it is incorrect to call execvp */
312 execv (cmd, argv);
313 _exit (1);
317 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
319 struct timeval tv;
320 SELECT_MASK rset;
321 SELECT_MASK eset;
323 int max_fd = 0;
324 int ready;
325 int i;
326 int received;
328 tv.tv_sec = timeout / 1000;
329 tv.tv_usec = (timeout % 1000) * 1000;
331 do {
332 FD_ZERO (&rset);
333 FD_ZERO (&eset);
335 for (i = 0; i < num_fd; i++)
337 FD_SET (fd[i], &rset);
338 FD_SET (fd[i], &eset);
340 if (fd[i] > max_fd)
341 max_fd = fd[i];
344 ready =
345 select (max_fd + 1, &rset, NULL, &eset, timeout == -1 ? NULL : &tv);
347 if (ready > 0)
349 received = 0;
351 for (i = 0; i < num_fd; i++)
353 if (FD_ISSET (fd[i], &rset))
355 is_set[i] = 1;
356 received = 1;
358 else
359 is_set[i] = 0;
362 #ifdef hpux
363 for (i = 0; i < num_fd; i++)
365 if (FD_ISSET (fd[i], &eset))
367 struct request_info ei;
369 /* Only query and reset error state if no file descriptor
370 is ready to be read, otherwise we will be signalling a
371 died process too early */
373 if (!received)
375 ioctl (fd[i], TIOCREQCHECK, &ei);
377 if (ei.request == TIOCCLOSE)
379 ioctl (fd[i], TIOCREQSET, &ei);
380 return -1;
383 ioctl (fd[i], TIOCREQSET, &ei);
385 ready--;
388 #endif
390 } while (timeout == -1 && ready == 0);
392 return ready;
395 #else
397 void
398 __gnat_kill (int pid, int sig)
403 __gnat_pipe (int *fd)
405 return -1;
409 __gnat_expect_fork (void)
411 return -1;
414 void
415 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
417 *pid = 0;
421 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
423 return -1;
425 #endif