OSDN Git Service

* gcc.dg/attr-weakref-1.c: Add exit (0) to avoid spurious
[pf3gnuchains/gcc-fork.git] / gcc / ada / expect.c
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,  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  ****************************************************************************/
32
33 #ifdef __alpha_vxworks
34 #include "vxWorks.h"
35 #endif
36
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
45
46 #include <sys/types.h>
47
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 #else
55 #include <sys/wait.h>
56 #endif
57
58 /* This file provides the low level functionalities needed to implement Expect
59    capabilities in GNAT.Expect.
60    Implementations for unix and windows systems is provided.
61    Dummy stubs are also provided for other systems. */
62
63 #ifdef _AIX
64 /* Work around the fact that gcc/cpp does not define "__unix__" under AiX.  */
65 #define __unix__
66 #endif
67
68 #ifdef __APPLE__
69 /* Work around the fact that gcc/cpp does not define "__unix__" on Darwin.  */
70 #define __unix__
71 #endif
72
73 #ifdef _WIN32
74
75 #include <windows.h>
76 #include <process.h>
77
78 void
79 __gnat_kill (int pid, int sig)
80 {
81   HANDLE process_handle;
82
83   if (sig == 9)
84     {
85       process_handle = OpenProcess (PROCESS_TERMINATE, FALSE, pid);
86       if (process_handle != NULL)
87         {
88           TerminateProcess (process_handle, 0);
89           CloseHandle (process_handle);
90         }
91     }
92 }
93
94 int
95 __gnat_waitpid (int pid)
96 {
97   HANDLE process_handle;
98   DWORD exitcode = 1;
99   DWORD res;
100
101   process_handle = OpenProcess (PROCESS_QUERY_INFORMATION, FALSE, pid);
102
103   if (process_handle != NULL)
104     {
105       res = WaitForSingleObject (process_handle, INFINITE);
106       GetExitCodeProcess (process_handle, &exitcode);
107       CloseHandle (process_handle);
108     }
109
110   return (int) exitcode;
111 }
112
113 int
114 __gnat_expect_fork (void)
115 {
116   return 0;
117 }
118
119 void
120 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
121 {
122   *pid = (int) spawnve (_P_NOWAIT, cmd, argv, NULL);
123 }
124
125 int
126 __gnat_pipe (int *fd)
127 {
128   HANDLE read, write;
129
130   CreatePipe (&read, &write, NULL, 0);
131   fd[0]=_open_osfhandle ((long)read, 0);
132   fd[1]=_open_osfhandle ((long)write, 0);
133   return 0;  /* always success */
134 }
135
136 int
137 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
138 {
139 #define MAX_DELAY 100
140
141   int i, delay, infinite = 0;
142   DWORD avail;
143   HANDLE handles[num_fd];
144
145   for (i = 0; i < num_fd; i++)
146     is_set[i] = 0;
147
148   for (i = 0; i < num_fd; i++)
149     handles[i] = (HANDLE) _get_osfhandle (fd [i]);
150
151   /* Start with small delays, and then increase them, to avoid polling too
152      much when waiting a long time */
153   delay = 5;
154
155   if (timeout < 0)
156     infinite = 1;
157
158   while (1)
159     {
160       for (i = 0; i < num_fd; i++)
161         {
162           if (!PeekNamedPipe (handles [i], NULL, 0, NULL, &avail, NULL))
163             return -1;
164
165           if (avail > 0)
166             {
167               is_set[i] = 1;
168               return 1;
169             }
170         }
171
172       if (!infinite && timeout <= 0)
173         return 0;
174
175       Sleep (delay);
176       timeout -= delay;
177
178       if (delay < MAX_DELAY)
179         delay += 10;
180     }
181 }
182
183 #elif defined (VMS)
184 #include <unistd.h>
185 #include <stdio.h>
186 #include <unixio.h>
187 #include <stdlib.h>
188 #include <string.h>
189 #include <vms/descrip.h>
190 #include <stdio.h>
191 #include <vms/stsdef.h>
192 #include <vms/iodef.h>
193
194 int
195 __gnat_waitpid (int pid)
196 {
197   int status = 0;
198
199   waitpid (pid, &status, 0);
200   status = WEXITSTATUS (status);
201
202   return status;
203 }
204
205 int
206 __gnat_pipe (int *fd)
207 {
208   return pipe (fd);
209 }
210
211 int
212 __gnat_expect_fork (void)
213 {
214   return -1;
215 }
216
217 void
218 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
219 {
220   *pid = (int) getpid ();
221   /* Since cmd is fully qualified, it is incorrect to call execvp */
222   execv (cmd, argv);
223   _exit (1);
224 }
225
226 int
227 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
228 {
229   int i, num, ready = 0;
230   unsigned int status;
231   int mbxchans [num_fd];
232   struct dsc$descriptor_s mbxname;
233   struct io_status_block {
234     short int condition;
235     short int count;
236     int dev;
237   } iosb;
238   char buf [256];
239
240   for (i = 0; i < num_fd; i++)
241     is_set[i] = 0;
242
243   for (i = 0; i < num_fd; i++)
244     {
245
246       /* Get name of the mailbox used in the pipe */
247       getname (fd [i], buf);
248
249       /* Assign a channel to the mailbox */
250       if (strlen (buf) > 0)
251         {
252           mbxname.dsc$w_length = strlen (buf);
253           mbxname.dsc$b_dtype = DSC$K_DTYPE_T;
254           mbxname.dsc$b_class = DSC$K_CLASS_S;
255           mbxname.dsc$a_pointer = buf;
256
257           status = SYS$ASSIGN (&mbxname, &mbxchans[i], 0, 0, 0);
258
259           if ((status & 1) != 1)
260             {
261               ready = -1;
262               return ready;
263             }
264         }
265     }
266
267   num = timeout / 100;
268
269   while (1)
270     {
271       for (i = 0; i < num_fd; i++)
272         {
273           if (mbxchans[i] > 0)
274             {
275
276               /* Peek in the mailbox to see if there's data */
277               status = SYS$QIOW
278                 (0, mbxchans[i], IO$_SENSEMODE|IO$M_READERCHECK,
279                  &iosb, 0, 0, 0, 0, 0, 0, 0, 0);
280
281               if ((status & 1) != 1)
282                 {
283                   ready = -1;
284                   goto deassign;
285                 }
286
287               if (iosb.count > 0)
288                 {
289                   is_set[i] = 1;
290                   ready = 1;
291                   goto deassign;
292                 }
293             }
294         }
295
296       if (timeout > 0 && num == 0)
297         {
298           ready = 0;
299           goto deassign;
300         }
301
302       usleep (100000);
303       num--;
304     }
305
306  deassign:
307
308   /* Deassign channels assigned above */
309   for (i = 0; i < num_fd; i++)
310     {
311       if (mbxchans[i] > 0)
312         status = SYS$DASSGN (mbxchans[i]);
313     }
314
315   return ready;
316 }
317
318 #elif defined (__unix__)
319
320 #ifdef __hpux__
321 #include <sys/ptyio.h>
322 #endif
323
324 #include <sys/time.h>
325
326 #ifndef NO_FD_SET
327 #define SELECT_MASK fd_set
328 #else /* !NO_FD_SET */
329 #ifndef _AIX
330 typedef long fd_mask;
331 #endif /* _AIX */
332 #ifdef _IBMR2
333 #define SELECT_MASK void
334 #else /* !_IBMR2 */
335 #define SELECT_MASK int
336 #endif /* !_IBMR2 */
337 #endif /* !NO_FD_SET */
338
339 void
340 __gnat_kill (int pid, int sig)
341 {
342   kill (pid, sig);
343 }
344
345 int
346 __gnat_waitpid (int pid)
347 {
348   int status = 0;
349
350   waitpid (pid, &status, 0);
351   status = WEXITSTATUS (status);
352
353   return status;
354 }
355
356 int
357 __gnat_pipe (int *fd)
358 {
359   return pipe (fd);
360 }
361
362 int
363 __gnat_expect_fork (void)
364 {
365   return fork ();
366 }
367
368 void
369 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
370 {
371   *pid = (int) getpid ();
372   /* Since cmd is fully qualified, it is incorrect to call execvp */
373   execv (cmd, argv);
374   _exit (1);
375 }
376
377 int
378 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
379 {
380   struct timeval tv;
381   SELECT_MASK rset;
382   SELECT_MASK eset;
383
384   int max_fd = 0;
385   int ready;
386   int i;
387   int received;
388
389   tv.tv_sec  = timeout / 1000;
390   tv.tv_usec = (timeout % 1000) * 1000;
391
392   do {
393     FD_ZERO (&rset);
394     FD_ZERO (&eset);
395
396     for (i = 0; i < num_fd; i++)
397       {
398         FD_SET (fd[i], &rset);
399         FD_SET (fd[i], &eset);
400
401         if (fd[i] > max_fd)
402           max_fd = fd[i];
403       }
404
405     ready =
406       select (max_fd + 1, &rset, NULL, &eset, timeout == -1 ? NULL : &tv);
407
408     if (ready > 0)
409       {
410         received = 0;
411
412         for (i = 0; i < num_fd; i++)
413           {
414             if (FD_ISSET (fd[i], &rset))
415               {
416                 is_set[i] = 1;
417                 received = 1;
418               }
419             else
420               is_set[i] = 0;
421           }
422
423 #ifdef __hpux__
424         for (i = 0; i < num_fd; i++)
425           {
426             if (FD_ISSET (fd[i], &eset))
427               {
428                 struct request_info ei;
429
430                 /* Only query and reset error state if no file descriptor
431                    is ready to be read, otherwise we will be signalling a
432                    died process too early */
433
434                 if (!received)
435                   {
436                     ioctl (fd[i], TIOCREQCHECK, &ei);
437
438                     if (ei.request == TIOCCLOSE)
439                       {
440                         ioctl (fd[i], TIOCREQSET, &ei);
441                         return -1;
442                       }
443
444                     ioctl (fd[i], TIOCREQSET, &ei);
445                   }
446                 ready--;
447               }
448           }
449 #endif
450       }
451   } while (timeout == -1 && ready == 0);
452
453   return ready;
454 }
455
456 #else
457
458 void
459 __gnat_kill (int pid, int sig)
460 {
461 }
462
463 int
464 __gnat_waitpid (int pid, int sig)
465 {
466   return 0;
467 }
468
469 int
470 __gnat_pipe (int *fd)
471 {
472   return -1;
473 }
474
475 int
476 __gnat_expect_fork (void)
477 {
478   return -1;
479 }
480
481 void
482 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
483 {
484   *pid = 0;
485 }
486
487 int
488 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
489 {
490   return -1;
491 }
492 #endif