Update concepts branch to revision 131834
[official-gcc.git] / gcc / ada / expect.c
blobaa18a3394818c7db8602c48f87dfdd11c70ec4d0
1 /****************************************************************************
2 * *
3 * GNAT COMPILER COMPONENTS *
4 * *
5 * E X P E C T *
6 * *
7 * C Implementation File *
8 * *
9 * Copyright (C) 2001-2007, 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 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, 51 Franklin Street, Fifth Floor, *
20 * Boston, MA 02110-1301, 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 #elif defined (__vxworks) && defined (__RTP__)
53 #include <wait.h>
54 #elif defined (__Lynx__)
55 /* ??? See comment in adaint.c. */
56 #define GCC_RESOURCE_H
57 #include <sys/wait.h>
58 #elif defined (__nucleus__)
59 /* No wait.h available on Nucleus */
60 #else
61 #include <sys/wait.h>
62 #endif
64 /* This file provides the low level functionalities needed to implement Expect
65 capabilities in GNAT.Expect.
66 Implementations for unix and windows systems is provided.
67 Dummy stubs are also provided for other systems. */
69 #ifdef _AIX
70 /* Work around the fact that gcc/cpp does not define "__unix__" under AiX. */
71 #define __unix__
72 #endif
74 #ifdef __APPLE__
75 /* Work around the fact that gcc/cpp does not define "__unix__" on Darwin. */
76 #define __unix__
77 #endif
79 #ifdef _WIN32
81 #include <windows.h>
82 #include <process.h>
84 void
85 __gnat_kill (int pid, int sig, int close)
87 if (sig == 9)
89 if ((HANDLE)pid != NULL)
91 TerminateProcess ((HANDLE)pid, 0);
92 if (close)
93 CloseHandle ((HANDLE)pid);
96 else if (sig == 2)
98 GenerateConsoleCtrlEvent (CTRL_C_EVENT, (HANDLE)pid);
99 if (close)
100 CloseHandle ((HANDLE)pid);
105 __gnat_waitpid (int pid)
107 DWORD exitcode = 1;
108 DWORD res;
110 if ((HANDLE)pid != NULL)
112 res = WaitForSingleObject ((HANDLE)pid, INFINITE);
113 GetExitCodeProcess ((HANDLE)pid, &exitcode);
114 CloseHandle ((HANDLE)pid);
117 return (int) exitcode;
121 __gnat_expect_fork (void)
123 return 0;
126 void
127 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
129 BOOL result;
130 STARTUPINFO SI;
131 PROCESS_INFORMATION PI;
132 SECURITY_ATTRIBUTES SA;
133 int csize = 1;
134 char *full_command;
135 int k;
137 /* compute the total command line length. */
138 k = 0;
139 while (argv[k])
141 csize += strlen (argv[k]) + 1;
142 k++;
145 full_command = (char *) malloc (csize);
146 full_command[0] = '\0';
148 /* Startup info. */
149 SI.cb = sizeof (STARTUPINFO);
150 SI.lpReserved = NULL;
151 SI.lpReserved2 = NULL;
152 SI.lpDesktop = NULL;
153 SI.cbReserved2 = 0;
154 SI.lpTitle = NULL;
155 SI.dwFlags = 0;
156 SI.wShowWindow = SW_HIDE;
158 /* Security attributes. */
159 SA.nLength = sizeof (SECURITY_ATTRIBUTES);
160 SA.bInheritHandle = TRUE;
161 SA.lpSecurityDescriptor = NULL;
163 k = 0;
164 while (argv[k])
166 strcat (full_command, argv[k]);
167 strcat (full_command, " ");
168 k++;
171 result = CreateProcess
172 (NULL, (char *) full_command, &SA, NULL, TRUE,
173 GetPriorityClass (GetCurrentProcess()), NULL, NULL, &SI, &PI);
175 free (full_command);
177 if (result == TRUE)
179 CloseHandle (PI.hThread);
180 *pid = (int) PI.hProcess;
182 else
183 *pid = -1;
187 __gnat_pipe (int *fd)
189 HANDLE read, write;
191 CreatePipe (&read, &write, NULL, 0);
192 fd[0]=_open_osfhandle ((long)read, 0);
193 fd[1]=_open_osfhandle ((long)write, 0);
194 return 0; /* always success */
198 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
200 #define MAX_DELAY 100
202 int i, delay, infinite = 0;
203 DWORD avail;
204 HANDLE handles[num_fd];
206 for (i = 0; i < num_fd; i++)
207 is_set[i] = 0;
209 for (i = 0; i < num_fd; i++)
210 handles[i] = (HANDLE) _get_osfhandle (fd [i]);
212 /* Start with small delays, and then increase them, to avoid polling too
213 much when waiting a long time */
214 delay = 5;
216 if (timeout < 0)
217 infinite = 1;
219 while (1)
221 for (i = 0; i < num_fd; i++)
223 if (!PeekNamedPipe (handles [i], NULL, 0, NULL, &avail, NULL))
224 return -1;
226 if (avail > 0)
228 is_set[i] = 1;
229 return 1;
233 if (!infinite && timeout <= 0)
234 return 0;
236 Sleep (delay);
237 timeout -= delay;
239 if (delay < MAX_DELAY)
240 delay += 10;
244 #elif defined (VMS)
245 #include <unistd.h>
246 #include <stdio.h>
247 #include <unixio.h>
248 #include <stdlib.h>
249 #include <string.h>
250 #include <vms/descrip.h>
251 #include <stdio.h>
252 #include <vms/stsdef.h>
253 #include <vms/iodef.h>
254 #include <signal.h>
256 void
257 __gnat_kill (int pid, int sig, int close)
259 kill (pid, sig);
263 __gnat_waitpid (int pid)
265 int status = 0;
267 waitpid (pid, &status, 0);
268 status = WEXITSTATUS (status);
270 return status;
274 __gnat_pipe (int *fd)
276 return pipe (fd);
280 __gnat_expect_fork (void)
282 return -1;
285 void
286 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
288 *pid = (int) getpid ();
289 /* Since cmd is fully qualified, it is incorrect to call execvp */
290 execv (cmd, argv);
291 _exit (1);
295 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
297 int i, num, ready = 0;
298 unsigned int status;
299 int mbxchans [num_fd];
300 struct dsc$descriptor_s mbxname;
301 struct io_status_block {
302 short int condition;
303 short int count;
304 int dev;
305 } iosb;
306 char buf [256];
308 for (i = 0; i < num_fd; i++)
309 is_set[i] = 0;
311 for (i = 0; i < num_fd; i++)
314 /* Get name of the mailbox used in the pipe */
315 getname (fd [i], buf);
317 /* Assign a channel to the mailbox */
318 if (strlen (buf) > 0)
320 mbxname.dsc$w_length = strlen (buf);
321 mbxname.dsc$b_dtype = DSC$K_DTYPE_T;
322 mbxname.dsc$b_class = DSC$K_CLASS_S;
323 mbxname.dsc$a_pointer = buf;
325 status = SYS$ASSIGN (&mbxname, &mbxchans[i], 0, 0, 0);
327 if ((status & 1) != 1)
329 ready = -1;
330 return ready;
335 num = timeout / 100;
337 while (1)
339 for (i = 0; i < num_fd; i++)
341 if (mbxchans[i] > 0)
344 /* Peek in the mailbox to see if there's data */
345 status = SYS$QIOW
346 (0, mbxchans[i], IO$_SENSEMODE|IO$M_READERCHECK,
347 &iosb, 0, 0, 0, 0, 0, 0, 0, 0);
349 if ((status & 1) != 1)
351 ready = -1;
352 goto deassign;
355 if (iosb.count > 0)
357 is_set[i] = 1;
358 ready = 1;
359 goto deassign;
364 if (timeout > 0 && num == 0)
366 ready = 0;
367 goto deassign;
370 usleep (100000);
371 num--;
374 deassign:
376 /* Deassign channels assigned above */
377 for (i = 0; i < num_fd; i++)
379 if (mbxchans[i] > 0)
380 status = SYS$DASSGN (mbxchans[i]);
383 return ready;
385 #elif defined (__unix__) && !defined (__nucleus__)
387 #ifdef __hpux__
388 #include <sys/ptyio.h>
389 #endif
391 #include <sys/time.h>
393 #ifndef NO_FD_SET
394 #define SELECT_MASK fd_set
395 #else /* !NO_FD_SET */
396 #ifndef _AIX
397 typedef long fd_mask;
398 #endif /* _AIX */
399 #ifdef _IBMR2
400 #define SELECT_MASK void
401 #else /* !_IBMR2 */
402 #define SELECT_MASK int
403 #endif /* !_IBMR2 */
404 #endif /* !NO_FD_SET */
406 void
407 __gnat_kill (int pid, int sig, int close)
409 kill (pid, sig);
413 __gnat_waitpid (int pid)
415 int status = 0;
417 waitpid (pid, &status, 0);
418 status = WEXITSTATUS (status);
420 return status;
424 __gnat_pipe (int *fd)
426 return pipe (fd);
430 __gnat_expect_fork (void)
432 return fork ();
435 void
436 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
438 *pid = (int) getpid ();
439 /* Since cmd is fully qualified, it is incorrect to call execvp */
440 execv (cmd, argv);
441 _exit (1);
445 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
447 struct timeval tv;
448 SELECT_MASK rset;
449 SELECT_MASK eset;
451 int max_fd = 0;
452 int ready;
453 int i;
454 int received;
456 tv.tv_sec = timeout / 1000;
457 tv.tv_usec = (timeout % 1000) * 1000;
459 do {
460 FD_ZERO (&rset);
461 FD_ZERO (&eset);
463 for (i = 0; i < num_fd; i++)
465 FD_SET (fd[i], &rset);
466 FD_SET (fd[i], &eset);
468 if (fd[i] > max_fd)
469 max_fd = fd[i];
472 ready =
473 select (max_fd + 1, &rset, NULL, &eset, timeout == -1 ? NULL : &tv);
475 if (ready > 0)
477 received = 0;
479 for (i = 0; i < num_fd; i++)
481 if (FD_ISSET (fd[i], &rset))
483 is_set[i] = 1;
484 received = 1;
486 else
487 is_set[i] = 0;
490 #ifdef __hpux__
491 for (i = 0; i < num_fd; i++)
493 if (FD_ISSET (fd[i], &eset))
495 struct request_info ei;
497 /* Only query and reset error state if no file descriptor
498 is ready to be read, otherwise we will be signalling a
499 died process too early */
501 if (!received)
503 ioctl (fd[i], TIOCREQCHECK, &ei);
505 if (ei.request == TIOCCLOSE)
507 ioctl (fd[i], TIOCREQSET, &ei);
508 return -1;
511 ioctl (fd[i], TIOCREQSET, &ei);
513 ready--;
516 #endif
518 } while (timeout == -1 && ready == 0);
520 return ready;
523 #else
525 void
526 __gnat_kill (int pid, int sig, int close)
531 __gnat_waitpid (int pid, int sig)
533 return 0;
537 __gnat_pipe (int *fd)
539 return -1;
543 __gnat_expect_fork (void)
545 return -1;
548 void
549 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
551 *pid = 0;
555 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
557 return -1;
559 #endif