diff options
Diffstat (limited to 'gcc-4.2.1/gcc/ada/expect.c')
-rw-r--r-- | gcc-4.2.1/gcc/ada/expect.c | 541 |
1 files changed, 541 insertions, 0 deletions
diff --git a/gcc-4.2.1/gcc/ada/expect.c b/gcc-4.2.1/gcc/ada/expect.c new file mode 100644 index 000000000..6d2cf86e3 --- /dev/null +++ b/gcc-4.2.1/gcc/ada/expect.c @@ -0,0 +1,541 @@ +/**************************************************************************** + * * + * GNAT COMPILER COMPONENTS * + * * + * E X P E C T * + * * + * C Implementation File * + * * + * Copyright (C) 2001-2005, AdaCore * + * * + * GNAT is free software; you can redistribute it and/or modify it under * + * terms of the GNU General Public License as published by the Free Soft- * + * ware Foundation; either version 2, or (at your option) any later ver- * + * sion. GNAT is distributed in the hope that it will be useful, but WITH- * + * OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * + * for more details. You should have received a copy of the GNU General * + * Public License distributed with GNAT; see file COPYING. If not, write * + * to the Free Software Foundation, 51 Franklin Street, Fifth Floor, * + * Boston, MA 02110-1301, USA. * + * * + * As a special exception, if you link this file with other files to * + * produce an executable, this file does not by itself cause the resulting * + * executable to be covered by the GNU General Public License. This except- * + * ion does not however invalidate any other reasons why the executable * + * file might be covered by the GNU Public License. * + * * + * GNAT was originally developed by the GNAT team at New York University. * + * Extensive contributions were provided by Ada Core Technologies Inc. * + * * + ****************************************************************************/ + +#ifdef __alpha_vxworks +#include "vxWorks.h" +#endif + +#ifdef IN_RTS +#define POSIX +#include "tconfig.h" +#include "tsystem.h" +#else +#include "config.h" +#include "system.h" +#endif + +#include <sys/types.h> + +#ifdef __MINGW32__ +#if OLD_MINGW +#include <sys/wait.h> +#endif +#elif defined (__vxworks) && defined (__RTP__) +#include <wait.h> +#else +#include <sys/wait.h> +#endif + +/* This file provides the low level functionalities needed to implement Expect + capabilities in GNAT.Expect. + Implementations for unix and windows systems is provided. + Dummy stubs are also provided for other systems. */ + +#ifdef _AIX +/* Work around the fact that gcc/cpp does not define "__unix__" under AiX. */ +#define __unix__ +#endif + +#ifdef __APPLE__ +/* Work around the fact that gcc/cpp does not define "__unix__" on Darwin. */ +#define __unix__ +#endif + +#ifdef _WIN32 + +#include <windows.h> +#include <process.h> + +void +__gnat_kill (int pid, int sig, int close) +{ + if (sig == 9) + { + if ((HANDLE)pid != NULL) + { + TerminateProcess ((HANDLE)pid, 0); + if (close) + CloseHandle ((HANDLE)pid); + } + } +} + +int +__gnat_waitpid (int pid) +{ + DWORD exitcode = 1; + DWORD res; + + if ((HANDLE)pid != NULL) + { + res = WaitForSingleObject ((HANDLE)pid, INFINITE); + GetExitCodeProcess ((HANDLE)pid, &exitcode); + CloseHandle ((HANDLE)pid); + } + + return (int) exitcode; +} + +int +__gnat_expect_fork (void) +{ + return 0; +} + +void +__gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[]) +{ + BOOL result; + STARTUPINFO SI; + PROCESS_INFORMATION PI; + SECURITY_ATTRIBUTES SA; + int csize = 1; + char *full_command; + int k; + + /* compute the total command line length. */ + k = 0; + while (argv[k]) + { + csize += strlen (argv[k]) + 1; + k++; + } + + full_command = (char *) malloc (csize); + full_command[0] = '\0'; + + /* Startup info. */ + SI.cb = sizeof (STARTUPINFO); + SI.lpReserved = NULL; + SI.lpReserved2 = NULL; + SI.lpDesktop = NULL; + SI.cbReserved2 = 0; + SI.lpTitle = NULL; + SI.dwFlags = 0; + SI.wShowWindow = SW_HIDE; + + /* Security attributes. */ + SA.nLength = sizeof (SECURITY_ATTRIBUTES); + SA.bInheritHandle = TRUE; + SA.lpSecurityDescriptor = NULL; + + k = 0; + while (argv[k]) + { + strcat (full_command, argv[k]); + strcat (full_command, " "); + k++; + } + + result = CreateProcess + (NULL, (char *) full_command, &SA, NULL, TRUE, + GetPriorityClass (GetCurrentProcess()), NULL, NULL, &SI, &PI); + + free (full_command); + + if (result == TRUE) + { + CloseHandle (PI.hThread); + *pid = (int) PI.hProcess; + } + else + *pid = -1; +} + +int +__gnat_pipe (int *fd) +{ + HANDLE read, write; + + CreatePipe (&read, &write, NULL, 0); + fd[0]=_open_osfhandle ((long)read, 0); + fd[1]=_open_osfhandle ((long)write, 0); + return 0; /* always success */ +} + +int +__gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set) +{ +#define MAX_DELAY 100 + + int i, delay, infinite = 0; + DWORD avail; + HANDLE handles[num_fd]; + + for (i = 0; i < num_fd; i++) + is_set[i] = 0; + + for (i = 0; i < num_fd; i++) + handles[i] = (HANDLE) _get_osfhandle (fd [i]); + + /* Start with small delays, and then increase them, to avoid polling too + much when waiting a long time */ + delay = 5; + + if (timeout < 0) + infinite = 1; + + while (1) + { + for (i = 0; i < num_fd; i++) + { + if (!PeekNamedPipe (handles [i], NULL, 0, NULL, &avail, NULL)) + return -1; + + if (avail > 0) + { + is_set[i] = 1; + return 1; + } + } + + if (!infinite && timeout <= 0) + return 0; + + Sleep (delay); + timeout -= delay; + + if (delay < MAX_DELAY) + delay += 10; + } +} + +#elif defined (VMS) +#include <unistd.h> +#include <stdio.h> +#include <unixio.h> +#include <stdlib.h> +#include <string.h> +#include <vms/descrip.h> +#include <stdio.h> +#include <vms/stsdef.h> +#include <vms/iodef.h> + +int +__gnat_waitpid (int pid) +{ + int status = 0; + + waitpid (pid, &status, 0); + status = WEXITSTATUS (status); + + return status; +} + +int +__gnat_pipe (int *fd) +{ + return pipe (fd); +} + +int +__gnat_expect_fork (void) +{ + return -1; +} + +void +__gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[]) +{ + *pid = (int) getpid (); + /* Since cmd is fully qualified, it is incorrect to call execvp */ + execv (cmd, argv); + _exit (1); +} + +int +__gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set) +{ + int i, num, ready = 0; + unsigned int status; + int mbxchans [num_fd]; + struct dsc$descriptor_s mbxname; + struct io_status_block { + short int condition; + short int count; + int dev; + } iosb; + char buf [256]; + + for (i = 0; i < num_fd; i++) + is_set[i] = 0; + + for (i = 0; i < num_fd; i++) + { + + /* Get name of the mailbox used in the pipe */ + getname (fd [i], buf); + + /* Assign a channel to the mailbox */ + if (strlen (buf) > 0) + { + mbxname.dsc$w_length = strlen (buf); + mbxname.dsc$b_dtype = DSC$K_DTYPE_T; + mbxname.dsc$b_class = DSC$K_CLASS_S; + mbxname.dsc$a_pointer = buf; + + status = SYS$ASSIGN (&mbxname, &mbxchans[i], 0, 0, 0); + + if ((status & 1) != 1) + { + ready = -1; + return ready; + } + } + } + + num = timeout / 100; + + while (1) + { + for (i = 0; i < num_fd; i++) + { + if (mbxchans[i] > 0) + { + + /* Peek in the mailbox to see if there's data */ + status = SYS$QIOW + (0, mbxchans[i], IO$_SENSEMODE|IO$M_READERCHECK, + &iosb, 0, 0, 0, 0, 0, 0, 0, 0); + + if ((status & 1) != 1) + { + ready = -1; + goto deassign; + } + + if (iosb.count > 0) + { + is_set[i] = 1; + ready = 1; + goto deassign; + } + } + } + + if (timeout > 0 && num == 0) + { + ready = 0; + goto deassign; + } + + usleep (100000); + num--; + } + + deassign: + + /* Deassign channels assigned above */ + for (i = 0; i < num_fd; i++) + { + if (mbxchans[i] > 0) + status = SYS$DASSGN (mbxchans[i]); + } + + return ready; +} + +#elif defined (__unix__) + +#ifdef __hpux__ +#include <sys/ptyio.h> +#endif + +#include <sys/time.h> + +#ifndef NO_FD_SET +#define SELECT_MASK fd_set +#else /* !NO_FD_SET */ +#ifndef _AIX +typedef long fd_mask; +#endif /* _AIX */ +#ifdef _IBMR2 +#define SELECT_MASK void +#else /* !_IBMR2 */ +#define SELECT_MASK int +#endif /* !_IBMR2 */ +#endif /* !NO_FD_SET */ + +void +__gnat_kill (int pid, int sig, int close) +{ + kill (pid, sig); +} + +int +__gnat_waitpid (int pid) +{ + int status = 0; + + waitpid (pid, &status, 0); + status = WEXITSTATUS (status); + + return status; +} + +int +__gnat_pipe (int *fd) +{ + return pipe (fd); +} + +int +__gnat_expect_fork (void) +{ + return fork (); +} + +void +__gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[]) +{ + *pid = (int) getpid (); + /* Since cmd is fully qualified, it is incorrect to call execvp */ + execv (cmd, argv); + _exit (1); +} + +int +__gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set) +{ + struct timeval tv; + SELECT_MASK rset; + SELECT_MASK eset; + + int max_fd = 0; + int ready; + int i; + int received; + + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + + do { + FD_ZERO (&rset); + FD_ZERO (&eset); + + for (i = 0; i < num_fd; i++) + { + FD_SET (fd[i], &rset); + FD_SET (fd[i], &eset); + + if (fd[i] > max_fd) + max_fd = fd[i]; + } + + ready = + select (max_fd + 1, &rset, NULL, &eset, timeout == -1 ? NULL : &tv); + + if (ready > 0) + { + received = 0; + + for (i = 0; i < num_fd; i++) + { + if (FD_ISSET (fd[i], &rset)) + { + is_set[i] = 1; + received = 1; + } + else + is_set[i] = 0; + } + +#ifdef __hpux__ + for (i = 0; i < num_fd; i++) + { + if (FD_ISSET (fd[i], &eset)) + { + struct request_info ei; + + /* Only query and reset error state if no file descriptor + is ready to be read, otherwise we will be signalling a + died process too early */ + + if (!received) + { + ioctl (fd[i], TIOCREQCHECK, &ei); + + if (ei.request == TIOCCLOSE) + { + ioctl (fd[i], TIOCREQSET, &ei); + return -1; + } + + ioctl (fd[i], TIOCREQSET, &ei); + } + ready--; + } + } +#endif + } + } while (timeout == -1 && ready == 0); + + return ready; +} + +#else + +void +__gnat_kill (int pid, int sig, int close) +{ +} + +int +__gnat_waitpid (int pid, int sig) +{ + return 0; +} + +int +__gnat_pipe (int *fd) +{ + return -1; +} + +int +__gnat_expect_fork (void) +{ + return -1; +} + +void +__gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[]) +{ + *pid = 0; +} + +int +__gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set) +{ + return -1; +} +#endif |