OSDN Git Service

* expect.c: Define __unix__ when __APPLE__ is defined.
[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-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  ****************************************************************************/
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 /* 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. */
50
51 #ifdef _AIX
52 /* Work around the fact that gcc/cpp does not define "__unix__" under AiX.  */
53 #define __unix__
54 #endif
55
56 #ifdef __APPLE__
57 /* Work around the fact that gcc/cpp does not define "__unix__" on Darwin.  */
58 #define __unix__
59 #endif
60
61 #ifdef _WIN32
62
63 #include <windows.h>
64 #include <process.h>
65
66 void
67 __gnat_kill (int pid, int sig)
68 {
69   HANDLE process_handle;
70
71   if (sig == 9)
72     {
73       process_handle = OpenProcess (PROCESS_TERMINATE, FALSE, pid);
74       if (process_handle != NULL)
75         TerminateProcess (process_handle, 0);
76     }
77 }
78
79 int
80 __gnat_expect_fork (void)
81 {
82   return 0;
83 }
84
85 void
86 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
87 {
88   *pid = (int) spawnve (_P_NOWAIT, cmd, argv, NULL);
89 }
90
91 int
92 __gnat_pipe (int *fd)
93 {
94   HANDLE read, write;
95
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 */
100 }
101
102 int
103 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
104 {
105 #define MAX_DELAY 100
106
107   int i, delay, infinite = 0;
108   DWORD avail;
109   HANDLE handles[num_fd];
110
111   for (i = 0; i < num_fd; i++)
112     is_set[i] = 0;
113
114   for (i = 0; i < num_fd; i++)
115     handles[i] = (HANDLE) _get_osfhandle (fd [i]);
116
117   /* Start with small delays, and then increase them, to avoid polling too
118      much when waiting a long time */
119   delay = 5;
120
121   if (timeout < 0)
122     infinite = 1;
123
124   while (1)
125     {
126       for (i = 0; i < num_fd; i++)
127         {
128           if (!PeekNamedPipe (handles [i], NULL, 0, NULL, &avail, NULL))
129             return -1;
130
131           if (avail > 0)
132             {
133               is_set[i] = 1;
134               return 1;
135             }
136         }
137
138       if (!infinite && timeout <= 0)
139         return 0;
140
141       Sleep (delay);
142       timeout -= delay;
143
144       if (delay < MAX_DELAY)
145         delay += 10;
146     }
147 }
148
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>
159
160 int
161 __gnat_pipe (int *fd)
162 {
163   return pipe (fd);
164 }
165
166 int
167 __gnat_expect_fork (void)
168 {
169   return -1;
170 }
171
172 void
173 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
174 {
175   *pid = (int) getpid ();
176   /* Since cmd is fully qualified, it is incorrect to call execvp */
177   execv (cmd, argv);
178   _exit (1);
179 }
180
181 int
182 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
183 {
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];
194
195   for (i = 0; i < num_fd; i++)
196     is_set[i] = 0;
197
198   for (i = 0; i < num_fd; i++)
199     {
200
201       /* Get name of the mailbox used in the pipe */
202       getname (fd [i], buf);
203
204       /* Assign a channel to the mailbox */
205       if (strlen (buf) > 0)
206         {
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;
211
212           status = SYS$ASSIGN (&mbxname, &mbxchans[i], 0, 0, 0);
213
214           if ((status & 1) != 1)
215             {
216               ready = -1;
217               return ready;
218             }
219         }
220     }
221
222   num = timeout / 100;
223
224   while (1)
225     {
226       for (i = 0; i < num_fd; i++)
227         {
228           if (mbxchans[i] > 0)
229             {
230
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);
235
236               if ((status & 1) != 1)
237                 {
238                   ready = -1;
239                   goto deassign;
240                 }
241
242               if (iosb.count > 0)
243                 {
244                   is_set[i] = 1;
245                   ready = 1;
246                   goto deassign;
247                 }
248             }
249         }
250
251       if (timeout > 0 && num == 0)
252         {
253           ready = 0;
254           goto deassign;
255         }
256
257       usleep (100000);
258       num--;
259     }
260
261  deassign:
262
263   /* Deassign channels assigned above */
264   for (i = 0; i < num_fd; i++)
265     {
266       if (mbxchans[i] > 0)
267         status = SYS$DASSGN (mbxchans[i]);
268     }
269
270   return ready;
271 }
272
273 #elif defined (__unix__)
274
275 #ifdef __hpux__
276 #include <sys/ptyio.h>
277 #endif
278
279 #include <sys/time.h>
280
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 */
293
294 void
295 __gnat_kill (int pid, int sig)
296 {
297   kill (pid, sig);
298 }
299
300 int
301 __gnat_pipe (int *fd)
302 {
303   return pipe (fd);
304 }
305
306 int
307 __gnat_expect_fork (void)
308 {
309   return fork ();
310 }
311
312 void
313 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
314 {
315   *pid = (int) getpid ();
316   /* Since cmd is fully qualified, it is incorrect to call execvp */
317   execv (cmd, argv);
318   _exit (1);
319 }
320
321 int
322 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
323 {
324   struct timeval tv;
325   SELECT_MASK rset;
326   SELECT_MASK eset;
327
328   int max_fd = 0;
329   int ready;
330   int i;
331   int received;
332
333   tv.tv_sec  = timeout / 1000;
334   tv.tv_usec = (timeout % 1000) * 1000;
335
336   do {
337     FD_ZERO (&rset);
338     FD_ZERO (&eset);
339
340     for (i = 0; i < num_fd; i++)
341       {
342         FD_SET (fd[i], &rset);
343         FD_SET (fd[i], &eset);
344
345         if (fd[i] > max_fd)
346           max_fd = fd[i];
347       }
348
349     ready =
350       select (max_fd + 1, &rset, NULL, &eset, timeout == -1 ? NULL : &tv);
351
352     if (ready > 0)
353       {
354         received = 0;
355
356         for (i = 0; i < num_fd; i++)
357           {
358             if (FD_ISSET (fd[i], &rset))
359               {
360                 is_set[i] = 1;
361                 received = 1;
362               }
363             else
364               is_set[i] = 0;
365           }
366
367 #ifdef __hpux__
368         for (i = 0; i < num_fd; i++)
369           {
370             if (FD_ISSET (fd[i], &eset))
371               {
372                 struct request_info ei;
373
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 */
377
378                 if (!received)
379                   {
380                     ioctl (fd[i], TIOCREQCHECK, &ei);
381
382                     if (ei.request == TIOCCLOSE)
383                       {
384                         ioctl (fd[i], TIOCREQSET, &ei);
385                         return -1;
386                       }
387
388                     ioctl (fd[i], TIOCREQSET, &ei);
389                   }
390                 ready--;
391               }
392           }
393 #endif
394       }
395   } while (timeout == -1 && ready == 0);
396
397   return ready;
398 }
399
400 #else
401
402 void
403 __gnat_kill (int pid, int sig)
404 {
405 }
406
407 int
408 __gnat_pipe (int *fd)
409 {
410   return -1;
411 }
412
413 int
414 __gnat_expect_fork (void)
415 {
416   return -1;
417 }
418
419 void
420 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
421 {
422   *pid = 0;
423 }
424
425 int
426 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
427 {
428   return -1;
429 }
430 #endif