hppa: Revise REG+D address support to allow long displacements before reload
[official-gcc.git] / gcc / ada / expect.c
blob7333c11d9542f942322345357a74d67b3742cfdf
1 /****************************************************************************
2 * *
3 * GNAT RUN-TIME COMPONENTS *
4 * *
5 * E X P E C T *
6 * *
7 * C Implementation File *
8 * *
9 * Copyright (C) 2001-2023, 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 #ifdef IN_RTS
33 #define POSIX
34 #include "runtime.h"
35 #include <unistd.h>
37 #else
38 #include "config.h"
39 #include "system.h"
40 #endif
42 #include "adaint.h"
43 #include <sys/types.h>
45 #if defined (__vxworks) && defined (__RTP__)
46 # include <wait.h>
47 #elif defined (__Lynx__)
48 /* ??? See comment in adaint.c. */
49 # define GCC_RESOURCE_H
50 # include <sys/wait.h>
51 #elif defined (__PikeOS__) || defined (__MINGW32__)
52 /* No wait.h available */
53 #else
54 #include <sys/wait.h>
55 #endif
57 /* This file provides the low level functionalities needed to implement Expect
58 capabilities in GNAT.Expect.
59 Implementations for unix and windows systems is provided.
60 Dummy stubs are also provided for other systems. */
62 #ifdef _AIX
63 /* Work around the fact that gcc/cpp does not define "__unix__" under AiX. */
64 #define __unix__
65 #endif
67 #ifdef __APPLE__
68 /* Work around the fact that gcc/cpp does not define "__unix__" on Darwin. */
69 #define __unix__
70 #endif
72 #ifdef _WIN32
74 #define WIN32_LEAN_AND_MEAN
75 #include <windows.h>
76 #include <process.h>
77 #include <signal.h>
78 #include <io.h>
79 #include "mingw32.h"
81 int
82 __gnat_waitpid (int pid)
84 HANDLE h = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pid);
85 DWORD exitcode = 1;
87 if (h != NULL)
89 (void) WaitForSingleObject (h, INFINITE);
90 GetExitCodeProcess (h, &exitcode);
91 CloseHandle (h);
94 __gnat_win32_remove_handle (NULL, pid);
95 return (int) exitcode;
98 int
99 __gnat_expect_fork (void)
101 return 0;
104 void
105 __gnat_expect_portable_execvp (int *pid, char *cmd ATTRIBUTE_UNUSED,
106 char *argv[])
108 *pid = __gnat_portable_no_block_spawn (argv);
112 __gnat_pipe (int *fd)
114 HANDLE read, write;
116 CreatePipe (&read, &write, NULL, 0);
117 fd[0]=_open_osfhandle ((intptr_t)read, 0);
118 fd[1]=_open_osfhandle ((intptr_t)write, 0);
119 return 0; /* always success */
123 __gnat_expect_poll (int *fd,
124 int num_fd,
125 int timeout,
126 int *dead_process,
127 int *is_set)
129 #define MAX_DELAY 100
131 int i, delay, infinite = 0;
132 DWORD avail;
133 HANDLE handles[num_fd];
135 *dead_process = 0;
137 for (i = 0; i < num_fd; i++)
138 is_set[i] = 0;
140 for (i = 0; i < num_fd; i++)
141 handles[i] = (HANDLE) _get_osfhandle (fd [i]);
143 /* Start with small delays, and then increase them, to avoid polling too
144 much when waiting a long time */
145 delay = 5;
147 if (timeout < 0)
148 infinite = 1;
150 while (1)
152 for (i = 0; i < num_fd; i++)
154 if (!PeekNamedPipe (handles [i], NULL, 0, NULL, &avail, NULL))
156 *dead_process = i + 1;
157 return -1;
159 if (avail > 0)
161 is_set[i] = 1;
162 return 1;
166 if (!infinite && timeout <= 0)
167 return 0;
169 Sleep (delay);
170 timeout -= delay;
172 if (delay < MAX_DELAY)
173 delay += 10;
177 #elif defined (VMS)
178 #include <unistd.h>
179 #include <stdio.h>
180 #include <unixio.h>
181 #include <stdlib.h>
182 #include <string.h>
183 #include <vms/descrip.h>
184 #include <stdio.h>
185 #include <vms/stsdef.h>
186 #include <vms/iodef.h>
187 #include <signal.h>
190 __gnat_waitpid (int pid)
192 int status = 0;
194 waitpid (pid, &status, 0);
195 status = WEXITSTATUS (status);
197 return status;
201 __gnat_pipe (int *fd)
203 return pipe (fd);
207 __gnat_expect_fork (void)
209 return -1;
212 void
213 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
215 *pid = (int) getpid ();
216 /* Since cmd is fully qualified, it is incorrect to call execvp */
217 execv (cmd, argv);
218 _exit (1);
222 __gnat_expect_poll (int *fd,
223 int num_fd,
224 int timeout,
225 int *dead_process,
226 int *is_set)
228 int i, num, ready = 0;
229 unsigned int status;
230 int mbxchans [num_fd];
231 struct dsc$descriptor_s mbxname;
232 struct io_status_block {
233 short int condition;
234 short int count;
235 int dev;
236 } iosb;
237 char buf [256];
239 *dead_process = 0;
241 for (i = 0; i < num_fd; i++)
242 is_set[i] = 0;
244 for (i = 0; i < num_fd; i++)
247 /* Get name of the mailbox used in the pipe */
248 getname (fd [i], buf);
250 /* Assign a channel to the mailbox */
251 if (strlen (buf) > 0)
253 mbxname.dsc$w_length = strlen (buf);
254 mbxname.dsc$b_dtype = DSC$K_DTYPE_T;
255 mbxname.dsc$b_class = DSC$K_CLASS_S;
256 mbxname.dsc$a_pointer = buf;
258 status = SYS$ASSIGN (&mbxname, &mbxchans[i], 0, 0, 0);
260 if ((status & 1) != 1)
262 ready = -1;
263 *dead_process = i + 1;
264 return ready;
269 num = timeout / 100;
271 while (1)
273 for (i = 0; i < num_fd; i++)
275 if (mbxchans[i] > 0)
278 /* Peek in the mailbox to see if there's data */
279 status = SYS$QIOW
280 (0, mbxchans[i], IO$_SENSEMODE|IO$M_READERCHECK,
281 &iosb, 0, 0, 0, 0, 0, 0, 0, 0);
283 if ((status & 1) != 1)
285 ready = -1;
286 goto deassign;
289 if (iosb.count > 0)
291 is_set[i] = 1;
292 ready = 1;
293 goto deassign;
298 if (timeout > 0 && num == 0)
300 ready = 0;
301 goto deassign;
304 usleep (100000);
305 num--;
308 deassign:
310 /* Deassign channels assigned above */
311 for (i = 0; i < num_fd; i++)
313 if (mbxchans[i] > 0)
314 status = SYS$DASSGN (mbxchans[i]);
317 return ready;
319 #elif defined (__unix__)
321 #ifdef __hpux__
322 #include <sys/ptyio.h>
323 #endif
325 #include <sys/time.h>
327 #ifndef NO_FD_SET
328 #define SELECT_MASK fd_set
329 #else /* !NO_FD_SET */
330 #ifndef _AIX
331 typedef long fd_mask;
332 #endif /* _AIX */
333 #ifdef _IBMR2
334 #define SELECT_MASK void
335 #else /* !_IBMR2 */
336 #define SELECT_MASK int
337 #endif /* !_IBMR2 */
338 #endif /* !NO_FD_SET */
341 __gnat_waitpid (int pid)
343 int status = 0;
345 if (waitpid (pid, &status, 0) == -1) {
346 return -1;
349 if (WIFEXITED (status)) {
350 status = WEXITSTATUS (status);
351 } else if (WIFSIGNALED (status)) {
352 status = WTERMSIG (status);
353 } else if (WIFSTOPPED (status)) {
354 status = WSTOPSIG (status);
357 return status;
361 __gnat_pipe (int *fd)
363 return pipe (fd);
367 __gnat_expect_fork (void)
369 int pid = fork();
370 if (pid == 0) {
371 __gnat_in_child_after_fork = 1;
373 return pid;
376 void
377 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
379 *pid = (int) getpid ();
380 /* Since cmd is fully qualified, it is incorrect to call execvp */
381 execv (cmd, argv);
382 _exit (1);
386 __gnat_expect_poll (int *fd,
387 int num_fd,
388 int timeout,
389 int *dead_process,
390 int *is_set)
392 struct timeval tv;
393 SELECT_MASK rset;
394 SELECT_MASK eset;
396 int max_fd = 0;
397 int ready;
398 int i;
399 #ifdef __hpux__
400 int received;
401 #endif
403 *dead_process = 0;
405 tv.tv_sec = timeout / 1000;
406 tv.tv_usec = (timeout % 1000) * 1000;
408 do {
409 FD_ZERO (&rset);
410 FD_ZERO (&eset);
412 for (i = 0; i < num_fd; i++)
414 FD_SET (fd[i], &rset);
415 FD_SET (fd[i], &eset);
417 if (fd[i] > max_fd)
418 max_fd = fd[i];
421 ready =
422 select (max_fd + 1, &rset, NULL, &eset, timeout == -1 ? NULL : &tv);
424 if (ready > 0)
426 #ifdef __hpux__
427 received = 0;
428 #endif
430 for (i = 0; i < num_fd; i++)
432 if (FD_ISSET (fd[i], &rset))
434 is_set[i] = 1;
435 #ifdef __hpux__
436 received = 1;
437 #endif
439 else
440 is_set[i] = 0;
443 #ifdef __hpux__
444 for (i = 0; i < num_fd; i++)
446 if (FD_ISSET (fd[i], &eset))
448 struct request_info ei;
450 /* Only query and reset error state if no file descriptor
451 is ready to be read, otherwise we will be signalling a
452 died process too early */
454 if (!received)
456 ioctl (fd[i], TIOCREQCHECK, &ei);
458 if (ei.request == TIOCCLOSE)
460 ioctl (fd[i], TIOCREQSET, &ei);
461 *dead_process = i + 1;
462 return -1;
465 ioctl (fd[i], TIOCREQSET, &ei);
467 ready--;
470 #endif
472 } while (timeout == -1 && ready == 0);
474 return ready;
477 #else
480 __gnat_waitpid (int pid ATTRIBUTE_UNUSED, int sig ATTRIBUTE_UNUSED)
482 return 0;
486 __gnat_pipe (int *fd ATTRIBUTE_UNUSED)
488 return -1;
492 __gnat_expect_fork (void)
494 return -1;
497 void
498 __gnat_expect_portable_execvp (int *pid ATTRIBUTE_UNUSED,
499 char *cmd ATTRIBUTE_UNUSED,
500 char *argv[] ATTRIBUTE_UNUSED)
502 *pid = 0;
506 __gnat_expect_poll (int *fd ATTRIBUTE_UNUSED,
507 int num_fd ATTRIBUTE_UNUSED,
508 int timeout ATTRIBUTE_UNUSED,
509 int *dead_process ATTRIBUTE_UNUSED,
510 int *is_set ATTRIBUTE_UNUSED)
512 *dead_process = 0;
513 return -1;
515 #endif