summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2015-04-01 16:43:50 -0700
committerH.J. Lu <hjl.tools@gmail.com>2015-04-17 07:39:54 -0700
commit463448deaf3d937bdc3b32634c8a164742e23b1d (patch)
tree1458b803f1ba1fd79a1f0d48f5c41602c75a6b5d
parenta94214bb1dea4a24ccb457da3522f1952fd5ae35 (diff)
downloadgcc-hjl/pr61954/master.tar.gz
Use s-crtl-ptr.ads for x32hjl/pr61954/master
Add s-crtl-ptr.ads and other files to convert integers to pointers for x32.
-rw-r--r--gcc/ada/adaint-x32.c2004
-rw-r--r--gcc/ada/adaint-x32.h313
-rw-r--r--gcc/ada/argv-x32.c123
-rw-r--r--gcc/ada/cstreams-x32.c224
-rw-r--r--gcc/ada/gcc-interface/Makefile.in7
-rw-r--r--gcc/ada/init-x32.c651
-rw-r--r--gcc/ada/mkdir-x32.c54
-rw-r--r--gcc/ada/s-crtl-x32.ads241
8 files changed, 3617 insertions, 0 deletions
diff --git a/gcc/ada/adaint-x32.c b/gcc/ada/adaint-x32.c
new file mode 100644
index 00000000000..733b4a89b14
--- /dev/null
+++ b/gcc/ada/adaint-x32.c
@@ -0,0 +1,2004 @@
+/****************************************************************************
+ * *
+ * GNAT COMPILER COMPONENTS *
+ * *
+ * A D A I N T *
+ * *
+ * C Implementation File *
+ * *
+ * Copyright (C) 2015, Free Software Foundation, Inc. *
+ * *
+ * 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 3, 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. *
+ * *
+ * As a special exception under Section 7 of GPL version 3, you are granted *
+ * additional permissions described in the GCC Runtime Library Exception, *
+ * version 3.1, as published by the Free Software Foundation. *
+ * *
+ * You should have received a copy of the GNU General Public License and *
+ * a copy of the GCC Runtime Library Exception along with this program; *
+ * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see *
+ * <http://www.gnu.org/licenses/>. *
+ * *
+ * GNAT was originally developed by the GNAT team at New York University. *
+ * Extensive contributions were provided by Ada Core Technologies Inc. *
+ * *
+ ****************************************************************************/
+
+/* This file contains those routines named by Import pragmas in
+ packages in the GNAT hierarchy (especially GNAT.OS_Lib) and in
+ package Osint. Many of the subprograms in OS_Lib import standard
+ library calls directly. This file contains all other routines. */
+
+/* Ensure access to errno is thread safe. */
+#define _REENTRANT
+#define _THREAD_SAFE
+
+#if !defined __linux__ && !defined __x86_64__ && !defined __ILP32__
+#error Unsupported platform.
+#endif
+
+#ifdef IN_RTS
+#include "tconfig.h"
+#include "tsystem.h"
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <time.h>
+
+/* We don't have libiberty, so use malloc. */
+#define xmalloc(S) malloc (S)
+#define xrealloc(V,S) realloc (V,S)
+#else
+#include "config.h"
+#include "system.h"
+#include "version.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <utime.h>
+#include <sys/wait.h>
+#include <utime.h>
+
+#include "adaint.h"
+
+/* Define symbols O_BINARY and O_TEXT as harmless zeroes if they are not
+ defined in the current system. On DOS-like systems these flags control
+ whether the file is opened/created in text-translation mode (CR/LF in
+ external file mapped to LF in internal file), but in Unix-like systems,
+ no text translation is required, so these flags have no effect. */
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#ifndef O_TEXT
+#define O_TEXT 0
+#endif
+
+#ifndef HOST_EXECUTABLE_SUFFIX
+#define HOST_EXECUTABLE_SUFFIX ""
+#endif
+
+#ifndef HOST_OBJECT_SUFFIX
+#define HOST_OBJECT_SUFFIX ".o"
+#endif
+
+#ifndef PATH_SEPARATOR
+#define PATH_SEPARATOR ':'
+#endif
+
+#ifndef DIR_SEPARATOR
+#define DIR_SEPARATOR '/'
+#endif
+
+/* Check for cross-compilation. */
+#if defined (CROSS_COMPILE) || defined (CROSS_DIRECTORY_STRUCTURE)
+#define IS_CROSS 1
+int __gnat_is_cross_compiler = 1;
+#else
+#undef IS_CROSS
+int __gnat_is_cross_compiler = 0;
+#endif
+
+char __gnat_dir_separator = DIR_SEPARATOR;
+
+char __gnat_path_separator = PATH_SEPARATOR;
+
+/* The GNAT_LIBRARY_TEMPLATE contains a list of expressions that define
+ the base filenames that libraries specified with -lsomelib options
+ may have. This is used by GNATMAKE to check whether an executable
+ is up-to-date or not. The syntax is
+
+ library_template ::= { pattern ; } pattern NUL
+ pattern ::= [ prefix ] * [ postfix ]
+
+ These should only specify names of static libraries as it makes
+ no sense to determine at link time if dynamic-link libraries are
+ up to date or not. Any libraries that are not found are supposed
+ to be up-to-date:
+
+ * if they are needed but not present, the link
+ will fail,
+
+ * otherwise they are libraries in the system paths and so
+ they are considered part of the system and not checked
+ for that reason.
+
+ ??? This should be part of a GNAT host-specific compiler
+ file instead of being included in all user applications
+ as well. This is only a temporary work-around for 3.11b. */
+
+#ifndef GNAT_LIBRARY_TEMPLATE
+#define GNAT_LIBRARY_TEMPLATE "lib*.a"
+#endif
+
+const char *__gnat_library_template = GNAT_LIBRARY_TEMPLATE;
+
+#include <sys/param.h>
+
+#ifdef MAXPATHLEN
+#define GNAT_MAX_PATH_LEN MAXPATHLEN
+#else
+#define GNAT_MAX_PATH_LEN 256
+#endif
+
+/* Used for runtime check that Ada constant File_Attributes_Size is no
+ less than the actual size of struct file_attributes (see Osint
+ initialization). */
+int __gnat_size_of_file_attributes = sizeof (struct file_attributes);
+
+/* The __gnat_max_path_len variable is used to export the maximum
+ length of a path name to Ada code. max_path_len is also provided
+ for compatibility with older GNAT versions, please do not use
+ it. */
+
+int __gnat_max_path_len = GNAT_MAX_PATH_LEN;
+int max_path_len = GNAT_MAX_PATH_LEN;
+
+/* Control whether we can use ACL on Windows. */
+
+int __gnat_use_acl = 1;
+
+/* The following macro HAVE_READDIR_R should be defined if the
+ system provides the routine readdir_r.
+ ... but we never define it anywhere??? */
+#undef HAVE_READDIR_R
+
+#define MAYBE_TO_PTR32(argv) argv
+
+/* Query information for the given file NAME and return it in STATBUF.
+ * Returns 0 for success, or errno value for failure.
+ */
+static int
+__gnat_stat (char *name, GNAT_STRUCT_STAT *statbuf)
+{
+ return GNAT_STAT (name, statbuf) == 0 ? 0 : errno;
+}
+
+static const char ATTR_UNSET = 127;
+
+/* Reset the file attributes as if no system call had been performed */
+
+static void
+gnat_reset_attributes (struct file_attributes* attr)
+{
+ attr->exists = ATTR_UNSET;
+ attr->error = EINVAL;
+
+ attr->writable = ATTR_UNSET;
+ attr->readable = ATTR_UNSET;
+ attr->executable = ATTR_UNSET;
+
+ attr->regular = ATTR_UNSET;
+ attr->symbolic_link = ATTR_UNSET;
+ attr->directory = ATTR_UNSET;
+
+ attr->timestamp = (OS_Time)-2;
+ attr->file_length = -1;
+}
+
+void
+__gnat_reset_attributes (uintptr_t attr_p)
+{
+ struct file_attributes* attr = (struct file_attributes *)attr_p;
+ gnat_reset_attributes (attr);
+}
+
+int
+__gnat_error_attributes (uintptr_t attr_p) {
+ struct file_attributes* attr = (struct file_attributes *)attr_p;
+ return attr->error;
+}
+
+OS_Time
+__gnat_current_time (void)
+{
+ time_t res = time (NULL);
+ return (OS_Time) res;
+}
+
+/* Return the current local time as a string in the ISO 8601 format of
+ "YYYY-MM-DD HH:MM:SS.SS". The returned string is 22 + 1 (NULL) characters
+ long. */
+
+void
+__gnat_current_time_string (uintptr_t result_p)
+{
+ char *result = (char *)result_p;
+ const char *format = "%Y-%m-%d %H:%M:%S";
+ /* Format string necessary to describe the ISO 8601 format */
+
+ const time_t t_val = time (NULL);
+
+ strftime (result, 22, format, localtime (&t_val));
+ /* Convert the local time into a string following the ISO format, copying
+ at most 22 characters into the result string. */
+
+ result [19] = '.';
+ result [20] = '0';
+ result [21] = '0';
+ /* The sub-seconds are manually set to zero since type time_t lacks the
+ precision necessary for nanoseconds. */
+}
+
+void
+__gnat_to_gm_time (uintptr_t p_time_p, uintptr_t p_year_p,
+ uintptr_t p_month_p, uintptr_t p_day_p,
+ uintptr_t p_hours_p, uintptr_t p_mins_p,
+ uintptr_t p_secs_p)
+{
+ OS_Time *p_time = (OS_Time *)p_time_p;
+ int *p_year = (int *)p_year_p;
+ int *p_month = (int *)p_month_p;
+ int *p_day = (int *)p_day_p;
+ int *p_hours = (int *)p_hours_p;
+ int *p_mins = (int *)p_mins_p;
+ int *p_secs = (int *)p_secs_p;
+ struct tm *res;
+ time_t time = (time_t) *p_time;
+
+ res = gmtime (&time);
+ if (res)
+ {
+ *p_year = res->tm_year;
+ *p_month = res->tm_mon;
+ *p_day = res->tm_mday;
+ *p_hours = res->tm_hour;
+ *p_mins = res->tm_min;
+ *p_secs = res->tm_sec;
+ }
+ else
+ *p_year = *p_month = *p_day = *p_hours = *p_mins = *p_secs = 0;
+}
+
+void
+__gnat_to_os_time (uintptr_t p_time_p, int year, int month, int day,
+ int hours, int mins, int secs)
+{
+ OS_Time *p_time = (OS_Time *)p_time_p;
+ struct tm v;
+
+ v.tm_year = year;
+ v.tm_mon = month;
+ v.tm_mday = day;
+ v.tm_hour = hours;
+ v.tm_min = mins;
+ v.tm_sec = secs;
+ v.tm_isdst = -1;
+
+ /* returns -1 of failing, this is s-os_lib Invalid_Time */
+
+ *p_time = (OS_Time) mktime (&v);
+}
+
+/* Place the contents of the symbolic link named PATH in the buffer BUF,
+ which has size BUFSIZ. If PATH is a symbolic link, then return the number
+ of characters of its content in BUF. Otherwise, return -1.
+ For systems not supporting symbolic links, always return -1. */
+
+int
+__gnat_readlink (uintptr_t path_p ATTRIBUTE_UNUSED,
+ uintptr_t buf_p ATTRIBUTE_UNUSED,
+ size_t bufsiz ATTRIBUTE_UNUSED)
+{
+ char *path = (char *)path_p;
+ char *buf = (char *)buf_p;
+ return readlink (path, buf, bufsiz);
+}
+
+/* Creates a symbolic link named NEWPATH which contains the string OLDPATH.
+ If NEWPATH exists it will NOT be overwritten.
+ For systems not supporting symbolic links, always return -1. */
+
+int
+__gnat_symlink (uintptr_t oldpath_p, uintptr_t newpath_p)
+{
+ char *oldpath = (char *)oldpath_p;
+ char *newpath = (char *)newpath_p;
+ return symlink (oldpath, newpath);
+}
+
+/* Try to lock a file, return 1 if success. */
+
+/* Version using link(), more secure over NFS. */
+/* See TN 6913-016 for discussion ??? */
+
+int
+__gnat_try_lock (uintptr_t dir_p, uintptr_t file_p)
+{
+ char *dir = (char *)dir_p;
+ char *file = (char *)file_p;
+ char full_path[256];
+ char temp_file[256];
+ GNAT_STRUCT_STAT stat_result;
+ int fd;
+
+ sprintf (full_path, "%s%c%s", dir, DIR_SEPARATOR, file);
+ sprintf (temp_file, "%s%cTMP-%ld-%ld",
+ dir, DIR_SEPARATOR, (long)getpid(), (long)getppid ());
+
+ /* Create the temporary file and write the process number. */
+ fd = open (temp_file, O_CREAT | O_WRONLY, 0600);
+ if (fd < 0)
+ return 0;
+
+ close (fd);
+
+ /* Link it with the new file. */
+ link (temp_file, full_path);
+
+ /* Count the references on the old one. If we have a count of two, then
+ the link did succeed. Remove the temporary file before returning. */
+ __gnat_stat (temp_file, &stat_result);
+ unlink (temp_file);
+ return stat_result.st_nlink == 2;
+}
+
+/* Return the maximum file name length. */
+
+int
+__gnat_get_maximum_file_name_length (void)
+{
+ return -1;
+}
+
+/* Return nonzero if file names are case sensitive. */
+
+static int file_names_case_sensitive_cache = -1;
+
+int
+__gnat_get_file_names_case_sensitive (void)
+{
+ if (file_names_case_sensitive_cache == -1)
+ {
+ const char *sensitive = getenv ("GNAT_FILE_NAME_CASE_SENSITIVE");
+
+ if (sensitive != NULL
+ && (sensitive[0] == '0' || sensitive[0] == '1')
+ && sensitive[1] == '\0')
+ file_names_case_sensitive_cache = sensitive[0] - '0';
+ else
+ {
+ /* By default, we suppose filesystems aren't case sensitive on
+ Windows and Darwin (but they are on arm-darwin). */
+ file_names_case_sensitive_cache = 1;
+ }
+ }
+ return file_names_case_sensitive_cache;
+}
+
+/* Return nonzero if environment variables are case sensitive. */
+
+int
+__gnat_get_env_vars_case_sensitive (void)
+{
+ return 1;
+}
+
+char
+__gnat_get_default_identifier_character_set (void)
+{
+ return '1';
+}
+
+/* Return the current working directory. */
+
+void
+__gnat_get_current_dir (uintptr_t dir_p, uintptr_t length_p)
+{
+ char *dir = (char *)dir_p;
+ int *length = (int *)length_p;
+ getcwd (dir, *length);
+
+ *length = strlen (dir);
+ if (dir [*length - 1] != DIR_SEPARATOR)
+ {
+ dir [*length] = DIR_SEPARATOR;
+ ++(*length);
+ }
+ dir[*length] = '\0';
+}
+
+/* Return the suffix for object files. */
+
+void
+__gnat_get_object_suffix_ptr (uintptr_t len_p, uintptr_t value_p)
+{
+ int *len = (int *)len_p;
+ const char **value = (const char **)value_p;
+ *value = HOST_OBJECT_SUFFIX;
+
+ if (*value == 0)
+ *len = 0;
+ else
+ *len = strlen (*value);
+
+ return;
+}
+
+/* Return the suffix for executable files. */
+
+void
+__gnat_get_executable_suffix_ptr (uintptr_t len_p, uintptr_t value_p)
+{
+ int *len = (int *)len_p;
+ const char **value = (const char **)value_p;
+ *value = HOST_EXECUTABLE_SUFFIX;
+ if (!*value)
+ *len = 0;
+ else
+ *len = strlen (*value);
+
+ return;
+}
+
+/* Return the suffix for debuggable files. Usually this is the same as the
+ executable extension. */
+
+void
+__gnat_get_debuggable_suffix_ptr (uintptr_t len_p, uintptr_t value_p)
+{
+ int *len = (int *)len_p;
+ const char **value = (const char **)value_p;
+ *value = HOST_EXECUTABLE_SUFFIX;
+
+ if (*value == 0)
+ *len = 0;
+ else
+ *len = strlen (*value);
+
+ return;
+}
+
+/* Returns the OS filename and corresponding encoding. */
+
+void
+__gnat_os_filename (uintptr_t filename_p,
+ uintptr_t w_filename_p ATTRIBUTE_UNUSED,
+ uintptr_t os_name_p,
+ uintptr_t o_length_p,
+ uintptr_t encoding_p ATTRIBUTE_UNUSED,
+ uintptr_t e_length_p)
+{
+ char *filename = (char *)filename_p;
+ char *os_name = ( char *)os_name_p;
+ int *o_length = (int *)o_length_p;
+ int *e_length = (int *)e_length_p;
+ strcpy (os_name, filename);
+ *o_length = strlen (filename);
+ *e_length = 0;
+}
+
+/* Delete a file. */
+
+int
+__gnat_unlink (uintptr_t path_p)
+{
+ char *path = (char *)path_p;
+ return unlink (path);
+}
+
+/* Rename a file. */
+
+int
+__gnat_rename (uintptr_t from_p, uintptr_t to_p)
+{
+ char *from = (char *)from_p;
+ char *to = (char *)to_p;
+ return rename (from, to);
+}
+
+/* Changing directory. */
+
+int
+__gnat_chdir (uintptr_t path_p)
+{
+ char *path = (char *)path_p;
+ return chdir (path);
+}
+
+/* Removing a directory. */
+
+int
+__gnat_rmdir (uintptr_t path_p)
+{
+ char *path = (char *)path_p;
+ return rmdir (path);
+}
+
+#include <wchar.h>
+
+int
+__gnat_fputwc(int c, uintptr_t stream_p)
+{
+ FILE *stream = (FILE *)stream_p;
+ return fputwc ((wchar_t)c, stream);
+}
+
+FILE *
+__gnat_fopen (uintptr_t path_p, uintptr_t mode_p,
+ int encoding ATTRIBUTE_UNUSED)
+{
+ char *path = (char *)path_p;
+ char *mode = (char *)mode_p;
+ return GNAT_FOPEN (path, mode);
+}
+
+FILE *
+__gnat_freopen (uintptr_t path_p,
+ uintptr_t mode_p,
+ uintptr_t stream_p,
+ int encoding ATTRIBUTE_UNUSED)
+{
+ char *path = (char *)path_p;
+ char *mode = (char *)mode_p;
+ FILE *stream = (FILE *)stream_p;
+ return freopen (path, mode, stream);
+}
+
+int
+__gnat_open_read (uintptr_t path_p, int fmode)
+{
+ char *path = (char *)path_p;
+ int fd;
+ int o_fmode = O_BINARY;
+
+ if (fmode)
+ o_fmode = O_TEXT;
+
+ fd = GNAT_OPEN (path, O_RDONLY | o_fmode);
+
+ return fd < 0 ? -1 : fd;
+}
+
+#define PERM (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
+
+int
+__gnat_open_rw (uintptr_t path_p, int fmode)
+{
+ char *path = (char *)path_p;
+ int fd;
+ int o_fmode = O_BINARY;
+
+ if (fmode)
+ o_fmode = O_TEXT;
+
+ fd = GNAT_OPEN (path, O_RDWR | o_fmode, PERM);
+
+ return fd < 0 ? -1 : fd;
+}
+
+int
+__gnat_open_create (uintptr_t path_p, int fmode)
+{
+ char *path = (char *)path_p;
+ int fd;
+ int o_fmode = O_BINARY;
+
+ if (fmode)
+ o_fmode = O_TEXT;
+
+ fd = GNAT_OPEN (path, O_WRONLY | O_CREAT | O_TRUNC | o_fmode, PERM);
+
+ return fd < 0 ? -1 : fd;
+}
+
+int
+__gnat_create_output_file (uintptr_t path_p)
+{
+ char *path = (char *)path_p;
+ int fd;
+ fd = GNAT_OPEN (path, O_WRONLY | O_CREAT | O_TRUNC | O_TEXT, PERM);
+
+ return fd < 0 ? -1 : fd;
+}
+
+int
+__gnat_create_output_file_new (uintptr_t path_p)
+{
+ char *path = (char *)path_p;
+ int fd;
+ fd = GNAT_OPEN (path, O_WRONLY | O_CREAT | O_TRUNC | O_TEXT | O_EXCL, PERM);
+
+ return fd < 0 ? -1 : fd;
+}
+
+int
+__gnat_open_append (uintptr_t path_p, int fmode)
+{
+ char *path = (char *)path_p;
+ int fd;
+ int o_fmode = O_BINARY;
+
+ if (fmode)
+ o_fmode = O_TEXT;
+
+ fd = GNAT_OPEN (path, O_WRONLY | O_CREAT | O_APPEND | o_fmode, PERM);
+
+ return fd < 0 ? -1 : fd;
+}
+
+/* Open a new file. Return error (-1) if the file already exists. */
+
+int
+__gnat_open_new (uintptr_t path_p, int fmode)
+{
+ char *path = (char *)path_p;
+ int fd;
+ int o_fmode = O_BINARY;
+
+ if (fmode)
+ o_fmode = O_TEXT;
+
+ fd = GNAT_OPEN (path, O_WRONLY | O_CREAT | O_EXCL | o_fmode, PERM);
+
+ return fd < 0 ? -1 : fd;
+}
+
+/* Open a new temp file. Return error (-1) if the file already exists. */
+
+int
+__gnat_open_new_temp (uintptr_t path_p, int fmode)
+{
+ char *path = (char *)path_p;
+ int fd;
+ int o_fmode = O_BINARY;
+
+ strcpy (path, "GNAT-XXXXXX");
+
+#if (defined (__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) \
+ || defined (linux) || defined(__GLIBC__)) && !defined (__vxworks)
+ return mkstemp (path);
+#elif defined (__Lynx__)
+ mktemp (path);
+#else
+ if (mktemp (path) == NULL)
+ return -1;
+#endif
+
+ if (fmode)
+ o_fmode = O_TEXT;
+
+ fd = GNAT_OPEN (path, O_WRONLY | O_CREAT | O_EXCL | o_fmode, PERM);
+ return fd < 0 ? -1 : fd;
+}
+
+int
+__gnat_open (uintptr_t path_p, int fmode)
+{
+ char *path = (char *)path_p;
+ int fd;
+
+ fd = GNAT_OPEN (path, fmode, PERM);
+
+ return fd < 0 ? -1 : fd;
+}
+
+/****************************************************************
+ ** Perform a call to GNAT_STAT or GNAT_FSTAT, and extract as much information
+ ** as possible from it, storing the result in a cache for later reuse
+ ****************************************************************/
+
+static void
+gnat_stat_to_attr (int fd, char* name, struct file_attributes* attr)
+{
+ GNAT_STRUCT_STAT statbuf;
+ int ret, error;
+
+ if (fd != -1) {
+ /* GNAT_FSTAT returns -1 and sets errno for failure */
+ ret = GNAT_FSTAT (fd, &statbuf);
+ error = ret ? errno : 0;
+
+ } else {
+ /* __gnat_stat returns errno value directly */
+ error = __gnat_stat (name, &statbuf);
+ ret = error ? -1 : 0;
+ }
+
+ /*
+ * A missing file is reported as an attr structure with error == 0 and
+ * exists == 0.
+ */
+
+ if (error == 0 || error == ENOENT)
+ attr->error = 0;
+ else
+ attr->error = error;
+
+ attr->regular = (!ret && S_ISREG (statbuf.st_mode));
+ attr->directory = (!ret && S_ISDIR (statbuf.st_mode));
+
+ if (!attr->regular)
+ attr->file_length = 0;
+ else
+ /* st_size may be 32 bits, or 64 bits which is converted to long. We
+ don't return a useful value for files larger than 2 gigabytes in
+ either case. */
+ attr->file_length = statbuf.st_size; /* all systems */
+
+ attr->exists = !ret;
+
+ /* on Windows requires extra system call, see __gnat_is_readable_file_attr */
+ attr->readable = (!ret && (statbuf.st_mode & S_IRUSR));
+ attr->writable = (!ret && (statbuf.st_mode & S_IWUSR));
+ attr->executable = (!ret && (statbuf.st_mode & S_IXUSR));
+
+ if (ret != 0) {
+ attr->timestamp = (OS_Time)-1;
+ } else {
+ attr->timestamp = (OS_Time)statbuf.st_mtime;
+ }
+}
+
+/****************************************************************
+ ** Return the number of bytes in the specified file
+ ****************************************************************/
+
+static __int64
+gnat_file_length_attr (int fd, char *name, struct file_attributes *attr)
+{
+ if (attr->file_length == -1)
+ gnat_stat_to_attr (fd, name, attr);
+ return attr->file_length;
+}
+
+__int64
+__gnat_file_length_attr (int fd, uintptr_t name_p, uintptr_t attr_p)
+{
+ char *name = (char *)name_p;
+ struct file_attributes *attr = (struct file_attributes *) attr_p;
+ return gnat_file_length_attr (fd, name, attr);
+}
+
+__int64
+__gnat_file_length (int fd)
+{
+ struct file_attributes attr;
+ gnat_reset_attributes (&attr);
+ return gnat_file_length_attr (fd, NULL, &attr);
+}
+
+long
+__gnat_file_length_long (int fd)
+{
+ struct file_attributes attr;
+ gnat_reset_attributes (&attr);
+ return (long)gnat_file_length_attr (fd, NULL, &attr);
+}
+
+__int64
+__gnat_named_file_length (uintptr_t name_p)
+{
+ char *name = (char *)name_p;
+ struct file_attributes attr;
+ gnat_reset_attributes (&attr);
+ return gnat_file_length_attr (-1, name, &attr);
+}
+
+/* Create a temporary filename and put it in string pointed to by
+ TMP_FILENAME. */
+
+void
+__gnat_tmp_name (uintptr_t tmp_filename_p)
+{
+ char *tmp_filename = (char *)tmp_filename_p;
+#define MAX_SAFE_PATH 1000
+ char *tmpdir = getenv ("TMPDIR");
+
+ /* If tmpdir is longer than MAX_SAFE_PATH, revert to default value to avoid
+ a buffer overflow. */
+ if (tmpdir == NULL || strlen (tmpdir) > MAX_SAFE_PATH)
+#ifdef __ANDROID__
+ strcpy (tmp_filename, "/cache/gnat-XXXXXX");
+#else
+ strcpy (tmp_filename, "/tmp/gnat-XXXXXX");
+#endif
+ else
+ sprintf (tmp_filename, "%s/gnat-XXXXXX", tmpdir);
+
+ close (mkstemp(tmp_filename));
+ tmpnam (tmp_filename);
+}
+
+/* Open directory and returns a DIR pointer. */
+
+DIR*
+__gnat_opendir (uintptr_t name_p)
+{
+ char *name = (char *)name_p;
+ return opendir (name);
+}
+
+/* Read the next entry in a directory. The returned string points somewhere
+ in the buffer. */
+
+#if defined (sun) && defined (__SVR4)
+/* For Solaris, be sure to use the 64-bit version, otherwise NFS reads may
+ fail with EOVERFLOW if the server uses 64-bit cookies. */
+#define dirent dirent64
+#define readdir readdir64
+#endif
+
+char *
+__gnat_readdir (uintptr_t dirp_p, uintptr_t buffer_p, uintptr_t len_p)
+{
+ DIR *dirp = (DIR *)dirp_p;
+ char *buffer = (char *)buffer_p;
+ int *len = (int *)len_p;
+#if defined (HAVE_READDIR_R)
+ /* If possible, try to use the thread-safe version. */
+ if (readdir_r (dirp, buffer) != NULL)
+ {
+ *len = strlen (((struct dirent*) buffer)->d_name);
+ return ((struct dirent*) buffer)->d_name;
+ }
+ else
+ return NULL;
+
+#else
+ struct dirent *dirent = (struct dirent *) readdir (dirp);
+
+ if (dirent != NULL)
+ {
+ strcpy (buffer, dirent->d_name);
+ *len = strlen (buffer);
+ return buffer;
+ }
+ else
+ return NULL;
+
+#endif
+}
+
+/* Close a directory entry. */
+
+int
+__gnat_closedir (uintptr_t dirp_p)
+{
+ DIR *dirp = (DIR *)dirp_p;
+ return closedir (dirp);
+}
+
+/* Returns 1 if readdir is thread safe, 0 otherwise. */
+
+int
+__gnat_readdir_is_thread_safe (void)
+{
+#ifdef HAVE_READDIR_R
+ return 1;
+#else
+ return 0;
+#endif
+}
+
+/* Return a GNAT time stamp given a file name. */
+
+static OS_Time
+gnat_file_time_name_attr (char *name, struct file_attributes *attr)
+{
+ if (attr->timestamp == (OS_Time)-2) {
+ gnat_stat_to_attr (-1, name, attr);
+ }
+ return attr->timestamp;
+}
+
+OS_Time
+__gnat_file_time_name_attr (uintptr_t name_p, uintptr_t attr_p)
+{
+ char *name = (char *)name_p;
+ struct file_attributes *attr = (struct file_attributes *) attr_p;
+ return gnat_file_time_name_attr (name, attr);
+}
+
+OS_Time
+__gnat_file_time_name (uintptr_t name_p)
+{
+ char *name = (char *)name_p;
+ struct file_attributes attr;
+ gnat_reset_attributes (&attr);
+ return gnat_file_time_name_attr (name, &attr);
+}
+
+/* Return a GNAT time stamp given a file descriptor. */
+
+static OS_Time
+__gnat_file_time_fd_attr (int fd, struct file_attributes *attr)
+{
+ if (attr->timestamp == (OS_Time)-2) {
+ gnat_stat_to_attr (fd, NULL, attr);
+ }
+
+ return attr->timestamp;
+}
+
+OS_Time
+__gnat_file_time_fd (int fd)
+{
+ struct file_attributes attr;
+ gnat_reset_attributes (&attr);
+ return __gnat_file_time_fd_attr (fd, &attr);
+}
+
+/* Set the file time stamp. */
+
+void
+__gnat_set_file_time_name (uintptr_t name_p, time_t time_stamp)
+{
+ char *name = (char *)name_p;
+ struct utimbuf utimbuf;
+ time_t t;
+
+ /* Set modification time to requested time. */
+ utimbuf.modtime = time_stamp;
+
+ /* Set access time to now in local time. */
+ t = time ((time_t) 0);
+ utimbuf.actime = mktime (localtime (&t));
+
+ utime (name, &utimbuf);
+}
+
+/* Get the list of installed standard libraries from the
+ HKEY_LOCAL_MACHINE\SOFTWARE\Ada Core Technologies\GNAT\Standard Libraries
+ key. */
+
+char *
+__gnat_get_libraries_from_registry (void)
+{
+ char *result = (char *) xmalloc (1);
+ result[0] = '\0';
+ return result;
+}
+
+/*************************************************************************
+ ** Check whether a file exists
+ *************************************************************************/
+
+static int
+gnat_file_exists_attr (char *name, struct file_attributes *attr)
+{
+ if (attr->exists == ATTR_UNSET)
+ gnat_stat_to_attr (-1, name, attr);
+
+ return attr->exists;
+}
+
+int
+__gnat_file_exists_attr (uintptr_t name_p, uintptr_t attr_p)
+{
+ char *name = (char *)name_p;
+ struct file_attributes *attr = (struct file_attributes *)attr_p;
+ return gnat_file_exists_attr (name, attr);
+}
+
+int
+__gnat_file_exists (uintptr_t name_p)
+{
+ char *name = (char *)name_p;
+ struct file_attributes attr;
+ gnat_reset_attributes (&attr);
+ return gnat_file_exists_attr (name, &attr);
+}
+
+/**********************************************************************
+ ** Whether name is an absolute path
+ **********************************************************************/
+
+static int
+gnat_is_absolute_path (char *name, int length)
+{
+ return (length != 0) && (*name == '/' || *name == DIR_SEPARATOR);
+}
+
+int
+__gnat_is_absolute_path (uintptr_t name_p, int length)
+{
+ char *name = (char *)name_p;
+ return gnat_is_absolute_path (name, length);
+}
+
+static int
+gnat_is_regular_file_attr (char *name, struct file_attributes *attr)
+{
+ if (attr->regular == ATTR_UNSET)
+ gnat_stat_to_attr (-1, name, attr);
+ return attr->regular;
+}
+
+int
+__gnat_is_regular_file_attr (uintptr_t name_p, uintptr_t attr_p)
+{
+ char *name = (char *)name_p;
+ struct file_attributes *attr = (struct file_attributes *) attr_p;
+ return gnat_is_regular_file_attr (name, attr);
+}
+
+static int
+gnat_is_regular_file (char *name)
+{
+ struct file_attributes attr;
+ gnat_reset_attributes (&attr);
+ return gnat_is_regular_file_attr (name, &attr);
+}
+
+int
+__gnat_is_regular_file (uintptr_t name_p)
+{
+ char *name = (char *)name_p;
+ return gnat_is_regular_file (name);
+}
+
+int
+__gnat_is_regular_file_fd (int fd)
+{
+ int ret;
+ GNAT_STRUCT_STAT statbuf;
+
+ ret = GNAT_FSTAT (fd, &statbuf);
+ return (!ret && S_ISREG (statbuf.st_mode));
+}
+
+static int
+gnat_is_directory_attr (char *name, struct file_attributes *attr)
+{
+ if (attr->directory == ATTR_UNSET)
+ gnat_stat_to_attr (-1, name, attr);
+ return attr->directory;
+}
+
+int
+__gnat_is_directory_attr (uintptr_t name_p, uintptr_t attr_p)
+{
+ char *name = (char *)name_p;
+ struct file_attributes *attr = (struct file_attributes *) attr_p;
+ return gnat_is_directory_attr (name, attr);
+}
+
+int
+__gnat_is_directory (uintptr_t name_p)
+{
+ char *name = (char *)name_p;
+ struct file_attributes attr;
+ gnat_reset_attributes (&attr);
+ return gnat_is_directory_attr (name, &attr);
+}
+
+static int
+gnat_is_readable_file_attr (char *name, struct file_attributes *attr)
+{
+ if (attr->readable == ATTR_UNSET)
+ gnat_stat_to_attr (-1, name, attr);
+ return attr->readable;
+}
+
+int
+__gnat_is_readable_file_attr (uintptr_t name_p, uintptr_t attr_p)
+{
+ char *name = (char *)name_p;
+ struct file_attributes *attr = (struct file_attributes *) attr_p;
+ return gnat_is_readable_file_attr (name, attr);
+}
+
+int
+__gnat_is_readable_file (uintptr_t name_p)
+{
+ char *name = (char *)name_p;
+ struct file_attributes attr;
+ gnat_reset_attributes (&attr);
+ return gnat_is_readable_file_attr (name, &attr);
+}
+
+static int
+gnat_is_writable_file_attr (char *name, struct file_attributes *attr)
+{
+ if (attr->writable == ATTR_UNSET)
+ gnat_stat_to_attr (-1, name, attr);
+ return attr->writable;
+}
+
+int
+__gnat_is_writable_file_attr (uintptr_t name_p, uintptr_t attr_p)
+{
+ char *name = (char *)name_p;
+ struct file_attributes *attr = (struct file_attributes *) attr_p;
+ return gnat_is_writable_file_attr (name, attr);
+}
+
+int
+__gnat_is_writable_file (uintptr_t name_p)
+{
+ char *name = (char *)name_p;
+ struct file_attributes attr;
+ gnat_reset_attributes (&attr);
+ return gnat_is_writable_file_attr (name, &attr);
+}
+
+static int
+gnat_is_executable_file_attr (char *name, struct file_attributes *attr)
+{
+ if (attr->executable == ATTR_UNSET)
+ gnat_stat_to_attr (-1, name, attr);
+ return attr->regular && attr->executable;
+}
+
+int
+__gnat_is_executable_file_attr (uintptr_t name_p, uintptr_t attr_p)
+{
+ char *name = (char *)name_p;
+ struct file_attributes *attr = (struct file_attributes *) attr_p;
+ return gnat_is_executable_file_attr (name, attr);
+}
+
+static int
+gnat_is_executable_file (char *name)
+{
+ struct file_attributes attr;
+ gnat_reset_attributes (&attr);
+ return gnat_is_executable_file_attr (name, &attr);
+}
+
+int
+__gnat_is_executable_file (uintptr_t name_p)
+{
+ char *name = (char *)name_p;
+ return gnat_is_executable_file (name);
+}
+
+void
+__gnat_set_writable (uintptr_t name_p)
+{
+ char *name = (char *)name_p;
+ GNAT_STRUCT_STAT statbuf;
+ if (GNAT_STAT (name, &statbuf) == 0)
+ {
+ statbuf.st_mode = statbuf.st_mode | S_IWUSR;
+ chmod (name, statbuf.st_mode);
+ }
+}
+
+/* must match definition in s-os_lib.ads */
+#define S_OWNER 1
+#define S_GROUP 2
+#define S_OTHERS 4
+
+void
+__gnat_set_executable (uintptr_t name_p, int mode)
+{
+ char *name = (char *)name_p;
+ GNAT_STRUCT_STAT statbuf;
+
+ if (GNAT_STAT (name, &statbuf) == 0)
+ {
+ if (mode & S_OWNER)
+ statbuf.st_mode = statbuf.st_mode | S_IXUSR;
+ if (mode & S_GROUP)
+ statbuf.st_mode = statbuf.st_mode | S_IXGRP;
+ if (mode & S_OTHERS)
+ statbuf.st_mode = statbuf.st_mode | S_IXOTH;
+ chmod (name, statbuf.st_mode);
+ }
+}
+
+void
+__gnat_set_non_writable (uintptr_t name_p)
+{
+ char *name = (char *)name_p;
+ GNAT_STRUCT_STAT statbuf;
+
+ if (GNAT_STAT (name, &statbuf) == 0)
+ {
+ statbuf.st_mode = statbuf.st_mode & 07577;
+ chmod (name, statbuf.st_mode);
+ }
+}
+
+void
+__gnat_set_readable (uintptr_t name_p)
+{
+ char *name = (char *)name_p;
+ GNAT_STRUCT_STAT statbuf;
+
+ if (GNAT_STAT (name, &statbuf) == 0)
+ {
+ chmod (name, statbuf.st_mode | S_IREAD);
+ }
+}
+
+void
+__gnat_set_non_readable (uintptr_t name_p)
+{
+ char *name = (char *)name_p;
+ GNAT_STRUCT_STAT statbuf;
+
+ if (GNAT_STAT (name, &statbuf) == 0)
+ {
+ chmod (name, statbuf.st_mode & (~S_IREAD));
+ }
+}
+
+static int
+gnat_is_symbolic_link_attr (char *name, struct file_attributes *attr)
+{
+ if (attr->symbolic_link == ATTR_UNSET)
+ {
+ int ret;
+ GNAT_STRUCT_STAT statbuf;
+ ret = GNAT_LSTAT (name, &statbuf);
+ attr->symbolic_link = (!ret && S_ISLNK (statbuf.st_mode));
+ }
+ return attr->symbolic_link;
+}
+
+int
+__gnat_is_symbolic_link_attr (uintptr_t name_p, uintptr_t attr_p)
+{
+ char *name = (char *)name_p;
+ struct file_attributes *attr = (struct file_attributes *) attr_p;
+ return gnat_is_symbolic_link_attr (name, attr);
+}
+
+int
+__gnat_is_symbolic_link (uintptr_t name_p)
+{
+ char *name = (char *)name_p;
+ struct file_attributes attr;
+ gnat_reset_attributes (&attr);
+ return gnat_is_symbolic_link_attr (name, &attr);
+}
+
+int
+__gnat_portable_spawn (uintptr_t args_p)
+{
+ char **args = (char **)args_p;
+ int status = 0;
+ int finished;
+ int pid;
+
+ pid = fork ();
+ if (pid < 0)
+ return -1;
+
+ if (pid == 0)
+ {
+ /* The child. */
+ if (execv (args[0], MAYBE_TO_PTR32 (args)) != 0)
+ _exit (1);
+ }
+
+ /* The parent. */
+ finished = waitpid (pid, &status, 0);
+
+ if (finished != pid || WIFEXITED (status) == 0)
+ return -1;
+
+ return WEXITSTATUS (status);
+}
+
+/* Create a copy of the given file descriptor.
+ Return -1 if an error occurred. */
+
+int
+__gnat_dup (int oldfd)
+{
+ return dup (oldfd);
+}
+
+/* Make newfd be the copy of oldfd, closing newfd first if necessary.
+ Return -1 if an error occurred. */
+
+int
+__gnat_dup2 (int oldfd ATTRIBUTE_UNUSED, int newfd ATTRIBUTE_UNUSED)
+{
+ return dup2 (oldfd, newfd);
+}
+
+int
+__gnat_number_of_cpus (void)
+{
+ int cores = (int) sysconf (_SC_NPROCESSORS_ONLN);
+ return cores;
+}
+
+int
+__gnat_portable_no_block_spawn (uintptr_t args_p)
+{
+ char **args = (char **)args_p;
+ int pid = fork ();
+
+ if (pid == 0)
+ {
+ /* The child. */
+ if (execv (args[0], MAYBE_TO_PTR32 (args)) != 0)
+ _exit (1);
+ }
+
+ return pid;
+}
+
+int
+__gnat_portable_wait (uintptr_t process_status_p)
+{
+ int *process_status = (int *)process_status_p;
+ int status = 0;
+ int pid = 0;
+
+ pid = waitpid (-1, &status, 0);
+ status = status & 0xffff;
+
+ *process_status = status;
+ return pid;
+}
+
+void
+__gnat_os_exit (int status)
+{
+ exit (status);
+}
+
+/* Locate file on path, that matches a predicate */
+
+static char *
+gnat_locate_file_with_predicate (char *file_name,
+ char *path_val,
+ int (*predicate)(char *))
+{
+ char *ptr;
+ char *file_path = (char *) alloca (strlen (file_name) + 1);
+ int absolute;
+
+ /* Return immediately if file_name is empty */
+
+ if (*file_name == '\0')
+ return 0;
+
+ /* Remove quotes around file_name if present */
+
+ ptr = file_name;
+ if (*ptr == '"')
+ ptr++;
+
+ strcpy (file_path, ptr);
+
+ ptr = file_path + strlen (file_path) - 1;
+
+ if (*ptr == '"')
+ *ptr = '\0';
+
+ /* Handle absolute pathnames. */
+
+ absolute = gnat_is_absolute_path (file_path, strlen (file_name));
+
+ if (absolute)
+ {
+ if (predicate (file_path))
+ return xstrdup (file_path);
+
+ return 0;
+ }
+
+ /* If file_name include directory separator(s), try it first as
+ a path name relative to the current directory */
+ for (ptr = file_name; *ptr && *ptr != '/' && *ptr != DIR_SEPARATOR; ptr++)
+ ;
+
+ if (*ptr != 0)
+ {
+ if (predicate (file_name))
+ return xstrdup (file_name);
+ }
+
+ if (path_val == 0)
+ return 0;
+
+ {
+ /* The result has to be smaller than path_val + file_name. */
+ char *file_path =
+ (char *) alloca (strlen (path_val) + strlen (file_name) + 2);
+
+ for (;;)
+ {
+ /* Skip the starting quote */
+
+ if (*path_val == '"')
+ path_val++;
+
+ for (ptr = file_path; *path_val && *path_val != PATH_SEPARATOR; )
+ *ptr++ = *path_val++;
+
+ /* If directory is empty, it is the current directory*/
+
+ if (ptr == file_path)
+ {
+ *ptr = '.';
+ }
+ else
+ ptr--;
+
+ /* Skip the ending quote */
+
+ if (*ptr == '"')
+ ptr--;
+
+ if (*ptr != '/' && *ptr != DIR_SEPARATOR)
+ *++ptr = DIR_SEPARATOR;
+
+ strcpy (++ptr, file_name);
+
+ if (predicate (file_path))
+ return xstrdup (file_path);
+
+ if (*path_val == 0)
+ return 0;
+
+ /* Skip path separator */
+
+ path_val++;
+ }
+ }
+
+ return 0;
+}
+
+/* Locate an executable file, give a Path value. */
+
+static char *
+gnat_locate_executable_file (char *file_name, char *path_val)
+{
+ return gnat_locate_file_with_predicate
+ (file_name, path_val, &gnat_is_executable_file);
+}
+
+/* Locate a regular file, give a Path value. */
+
+char *
+__gnat_locate_regular_file (uintptr_t file_name_p, uintptr_t path_val_p)
+{
+ char *file_name = (char *)file_name_p;
+ char *path_val = (char *)path_val_p;
+ return gnat_locate_file_with_predicate
+ (file_name, path_val, &gnat_is_regular_file);
+}
+
+/* Locate an executable given a Path argument. This routine is only used by
+ gnatbl and should not be used otherwise. Use locate_exec_on_path
+ instead. */
+
+static char *
+gnat_locate_exec (char *exec_name, char *path_val)
+{
+ char *ptr;
+ if (!strstr (exec_name, HOST_EXECUTABLE_SUFFIX))
+ {
+ char *full_exec_name =
+ (char *) alloca
+ (strlen (exec_name) + strlen (HOST_EXECUTABLE_SUFFIX) + 1);
+
+ strcpy (full_exec_name, exec_name);
+ strcat (full_exec_name, HOST_EXECUTABLE_SUFFIX);
+ ptr = gnat_locate_executable_file (full_exec_name, path_val);
+
+ if (ptr == 0)
+ return gnat_locate_executable_file (exec_name, path_val);
+ return ptr;
+ }
+ else
+ return gnat_locate_executable_file (exec_name, path_val);
+}
+
+char *
+__gnat_locate_exec (uintptr_t exec_name_p, uintptr_t path_val_p)
+{
+ char *exec_name = (char *)exec_name_p;
+ char *path_val = (char *)path_val_p;
+ return gnat_locate_exec (exec_name, path_val);
+}
+
+/* Locate an executable using the Systems default PATH. */
+
+char *
+__gnat_locate_exec_on_path (uintptr_t exec_name_p)
+{
+ char *exec_name = (char *)exec_name_p;
+ char *apath_val;
+
+ char *path_val = getenv ("PATH");
+
+ if (path_val == NULL) return NULL;
+ apath_val = (char *) alloca (strlen (path_val) + 1);
+ strcpy (apath_val, path_val);
+ return gnat_locate_exec (exec_name, apath_val);
+}
+
+/* Dummy functions for Osint import for non-VMS systems.
+ ??? To be removed. */
+
+int
+__gnat_to_canonical_file_list_init (uintptr_t dirspec ATTRIBUTE_UNUSED,
+ int onlydirs ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+char *
+__gnat_to_canonical_file_list_next (void)
+{
+ static char empty[] = "";
+ return empty;
+}
+
+void
+__gnat_to_canonical_file_list_free (void)
+{
+}
+
+char *
+__gnat_to_canonical_dir_spec (uintptr_t dirspec_p,
+ int prefixflag ATTRIBUTE_UNUSED)
+{
+ char *dirspec = (char *)dirspec_p;
+ return dirspec;
+}
+
+char *
+__gnat_to_canonical_file_spec (uintptr_t filespec_p)
+{
+ char *filespec = (char *)filespec_p;
+ return filespec;
+}
+
+char *
+__gnat_to_canonical_path_spec (uintptr_t pathspec_p)
+{
+ char *pathspec = (char *)pathspec_p;
+ return pathspec;
+}
+
+char *
+__gnat_to_host_dir_spec (uintptr_t dirspec_p,
+ int prefixflag ATTRIBUTE_UNUSED)
+{
+ char *dirspec = (char *)dirspec_p;
+ return dirspec;
+}
+
+char *
+__gnat_to_host_file_spec (uintptr_t filespec_p)
+{
+ char *filespec = (char *)filespec_p;
+ return filespec;
+}
+
+void
+__gnat_adjust_os_resource_limits (void)
+{
+}
+
+int __gnat_argument_needs_quote = 0;
+
+/* This option is used to enable/disable object files handling from the
+ binder file by the GNAT Project module. For example, this is disabled on
+ Windows (prior to GCC 3.4) as it is already done by the mdll module.
+ Stating with GCC 3.4 the shared libraries are not based on mdll
+ anymore as it uses the GCC's -shared option */
+int __gnat_prj_add_obj_files = 1;
+
+/* char used as prefix/suffix for environment variables */
+char __gnat_environment_char = '$';
+
+/* This functions copy the file attributes from a source file to a
+ destination file.
+
+ mode = 0 : In this mode copy only the file time stamps (last access and
+ last modification time stamps).
+
+ mode = 1 : In this mode, time stamps and read/write/execute attributes are
+ copied.
+
+ Returns 0 if operation was successful and -1 in case of error. */
+
+int
+__gnat_copy_attribs (uintptr_t from_p, uintptr_t to_p, int mode)
+{
+ char *from = (char *)from_p;
+ char *to = (char *)to_p;
+ GNAT_STRUCT_STAT fbuf;
+ struct utimbuf tbuf;
+
+ if (GNAT_STAT (from, &fbuf) == -1)
+ {
+ return -1;
+ }
+
+ tbuf.actime = fbuf.st_atime;
+ tbuf.modtime = fbuf.st_mtime;
+
+ if (utime (to, &tbuf) == -1)
+ {
+ return -1;
+ }
+
+ if (mode == 1)
+ {
+ if (chmod (to, fbuf.st_mode) == -1)
+ {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int
+__gnat_lseek (int fd, long offset, int whence)
+{
+ return (int) lseek (fd, offset, whence);
+}
+
+/* This function returns the major version number of GCC being used. */
+int
+get_gcc_version (void)
+{
+#ifdef IN_RTS
+ return __GNUC__;
+#else
+ return (int) (version_string[0] - '0');
+#endif
+}
+
+/*
+ * Set Close_On_Exec as indicated.
+ * Note: this is used for both GNAT.OS_Lib and GNAT.Sockets.
+ */
+
+int
+__gnat_set_close_on_exec (int fd ATTRIBUTE_UNUSED,
+ int close_on_exec_p ATTRIBUTE_UNUSED)
+{
+ int flags = fcntl (fd, F_GETFD, 0);
+ if (flags < 0)
+ return flags;
+ if (close_on_exec_p)
+ flags |= FD_CLOEXEC;
+ else
+ flags &= ~FD_CLOEXEC;
+ return fcntl (fd, F_SETFD, flags);
+}
+
+/* Indicates if platforms supports automatic initialization through the
+ constructor mechanism */
+int
+__gnat_binder_supports_auto_init (void)
+{
+ return 1;
+}
+
+/* Indicates that Stand-Alone Libraries are automatically initialized through
+ the constructor mechanism */
+int
+__gnat_sals_init_using_constructors (void)
+{
+ return 1;
+}
+
+#if defined (__ANDROID__)
+
+#include <pthread.h>
+
+void *
+__gnat_lwp_self (void)
+{
+ return (void *) pthread_self ();
+}
+
+#elif defined (linux)
+/* There is no function in the glibc to retrieve the LWP of the current
+ thread. We need to do a system call in order to retrieve this
+ information. */
+#include <sys/syscall.h>
+void *
+__gnat_lwp_self (void)
+{
+ return (void *) syscall (__NR_gettid);
+}
+
+#include <sched.h>
+
+/* glibc versions earlier than 2.7 do not define the routines to handle
+ dynamically allocated CPU sets. For these targets, we use the static
+ versions. */
+
+#ifdef CPU_ALLOC
+
+/* Dynamic cpu sets */
+
+cpu_set_t *
+__gnat_cpu_alloc (size_t count)
+{
+ return CPU_ALLOC (count);
+}
+
+size_t
+__gnat_cpu_alloc_size (size_t count)
+{
+ return CPU_ALLOC_SIZE (count);
+}
+
+void
+__gnat_cpu_free (uintptr_t set_p)
+{
+ cpu_set_t *set = (cpu_set_t *)set_p;
+ CPU_FREE (set);
+}
+
+void
+__gnat_cpu_zero (size_t count, uintptr_t set_p)
+{
+ cpu_set_t *set = (cpu_set_t *)set_p;
+ CPU_ZERO_S (count, set);
+}
+
+void
+__gnat_cpu_set (int cpu, size_t count, uintptr_t set_p)
+{
+ cpu_set_t *set = (cpu_set_t *)set_p;
+ /* Ada handles CPU numbers starting from 1, while C identifies the first
+ CPU by a 0, so we need to adjust. */
+ CPU_SET_S (cpu - 1, count, set);
+}
+
+#else /* !CPU_ALLOC */
+
+/* Static cpu sets */
+
+cpu_set_t *
+__gnat_cpu_alloc (size_t count ATTRIBUTE_UNUSED)
+{
+ return (cpu_set_t *) xmalloc (sizeof (cpu_set_t));
+}
+
+size_t
+__gnat_cpu_alloc_size (size_t count ATTRIBUTE_UNUSED)
+{
+ return sizeof (cpu_set_t);
+}
+
+void
+__gnat_cpu_free (uintptr_t set_p)
+{
+ cpu_set_t *set = (cpu_set_t *)set_p;
+ free (set);
+}
+
+void
+__gnat_cpu_zero (size_t count ATTRIBUTE_UNUSED, uintptr_t set_p)
+{
+ cpu_set_t *set = (cpu_set_t *)set_p;
+ CPU_ZERO (set);
+}
+
+void
+__gnat_cpu_set (int cpu, size_t count ATTRIBUTE_UNUSED, uintptr_t set_p)
+{
+ cpu_set_t *set = (cpu_set_t *)set_p;
+ /* Ada handles CPU numbers starting from 1, while C identifies the first
+ CPU by a 0, so we need to adjust. */
+ CPU_SET (cpu - 1, set);
+}
+#endif /* !CPU_ALLOC */
+#endif /* linux */
+
+/* Return the load address of the executable, or 0 if not known. In the
+ specific case of error, (void *)-1 can be returned. Beware: this unit may
+ be in a shared library. As low-level units are needed, we allow #include
+ here. */
+
+#if defined (__APPLE__)
+#include <mach-o/dyld.h>
+#elif 0 && defined (__linux__)
+#include <link.h>
+#endif
+
+const void *
+__gnat_get_executable_load_address (void)
+{
+#if defined (__APPLE__)
+ return _dyld_get_image_header (0);
+
+#elif 0 && defined (__linux__)
+ /* Currently disabled as it needs at least -ldl. */
+ struct link_map *map = _r_debug.r_map;
+
+ return (const void *)map->l_addr;
+
+#else
+ return NULL;
+#endif
+}
+
+size_t
+__gnat_strlen (uintptr_t s)
+{
+ return strlen ((const char *)s);
+}
+
+char *
+__gnat_strncpy (uintptr_t dest, uintptr_t src, size_t n)
+{
+ return strncpy ((char *)dest, (const char *)src, n);
+}
+
+void *
+__gnat_memcpy (uintptr_t dest, uintptr_t src, size_t n)
+{
+ return memcpy ((void *)dest, (const void *)src, n);
+}
+
+void *
+__gnat_memmove (uintptr_t dest, uintptr_t src, size_t n)
+{
+ return memmove ((void *)dest, (const void *)src, n);
+}
+
+int
+__gnat_atoi (uintptr_t nptr)
+{
+ return atoi ((const char *)nptr);
+}
+
+ssize_t
+__gnat_read (int fd, uintptr_t buf, size_t count)
+{
+ return read (fd, (void *)buf, count);
+}
+
+ssize_t
+__gnat_write (int fd, uintptr_t buf, size_t count)
+{
+ return write (fd, (const void *)buf, count);
+}
+
+char *
+__gnat_x32_getenv (uintptr_t name)
+{
+ return getenv ((const char *)name);
+}
+
+char *
+__gnat_mktemp (uintptr_t template)
+{
+ return mktemp ((char *)template);
+}
+
+char *
+__gnat_tmpnam (uintptr_t s)
+{
+ return tmpnam ((char *)s);
+}
+
+void
+__gnat_clearerr (uintptr_t stream)
+{
+ clearerr ((FILE *)stream);
+}
+
+int
+__gnat_fclose (uintptr_t stream)
+{
+ return fclose ((FILE *)stream);
+}
+
+FILE *
+__gnat_fdopen (int fd, uintptr_t mode)
+{
+ return fdopen (fd, (const char *)mode);
+}
+
+int
+__gnat_fflush (uintptr_t stream)
+{
+ return fflush ((FILE *)stream);
+}
+
+int
+__gnat_fgetc (uintptr_t stream)
+{
+ return fgetc ((FILE *)stream);
+}
+
+char *
+__gnat_fgets (uintptr_t s, int size, uintptr_t stream)
+{
+ return fgets ((char *)s, size, (FILE *)stream);
+}
+
+int
+__gnat_fputc (int c, uintptr_t stream)
+{
+ return fputc (c, (FILE *)stream);
+}
+
+int
+__gnat_fputs (uintptr_t s, uintptr_t stream)
+{
+ return fputs ((char *)s, (FILE *)stream);
+}
+
+int
+__gnat_ungetc (int c, uintptr_t stream)
+{
+ return ungetc (c, (FILE *)stream);
+}
+
+int
+__gnat_setvbuf (uintptr_t stream, uintptr_t buf, int mode, size_t size)
+{
+ return setvbuf ((FILE *)stream, (char *)buf, mode, size);
+}
+
+int
+__gnat_fseek (uintptr_t stream, long offset, int whence)
+{
+ return fseek ((FILE *)stream, offset, whence);
+}
+
+void
+__gnat_rewind (uintptr_t stream)
+{
+ rewind ((FILE *)stream);
+}
+
+int
+__gnat_pclose (uintptr_t stream)
+{
+ return pclose ((FILE *)stream);
+}
+
+FILE *
+__gnat_popen (uintptr_t command, uintptr_t type)
+{
+ return popen ((const char *)command, (const char *)type);
+}
+
+void *
+__gnat_x32_realloc (uintptr_t ptr, size_t size)
+{
+ return realloc ((void *)ptr, size);
+}
+
+void
+__gnat_x32_free (uintptr_t ptr)
+{
+ free ((void *)ptr);
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/ada/adaint-x32.h b/gcc/ada/adaint-x32.h
new file mode 100644
index 00000000000..b78759de1ef
--- /dev/null
+++ b/gcc/ada/adaint-x32.h
@@ -0,0 +1,313 @@
+/****************************************************************************
+ * *
+ * GNAT COMPILER COMPONENTS *
+ * *
+ * A D A I N T *
+ * *
+ * C Header File *
+ * *
+ * Copyright (C) 2015, Free Software Foundation, Inc. *
+ * *
+ * 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 3, 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. *
+ * *
+ * As a special exception under Section 7 of GPL version 3, you are granted *
+ * additional permissions described in the GCC Runtime Library Exception, *
+ * version 3.1, as published by the Free Software Foundation. *
+ * *
+ * You should have received a copy of the GNU General Public License and *
+ * a copy of the GCC Runtime Library Exception along with this program; *
+ * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see *
+ * <http://www.gnu.org/licenses/>. *
+ * *
+ * GNAT was originally developed by the GNAT team at New York University. *
+ * Extensive contributions were provided by Ada Core Technologies Inc. *
+ * *
+ ****************************************************************************/
+
+/* wrappers for run-time functions with pointer arguments. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <dirent.h>
+
+/* Constants used for the form parameter encoding values */
+#define Encoding_UTF8 0 /* UTF-8 */
+#define Encoding_8bits 1 /* Standard 8bits, CP_ACP on Windows. */
+#define Encoding_Unspecified 2 /* Based on GNAT_CODE_PAGE env variable. */
+
+/* Large file support. It is unclear what portable mechanism we can use to
+ determine at compile time what support the system offers for large files.
+ For now we just list the platforms we have manually tested. */
+
+#define GNAT_FOPEN fopen64
+#define GNAT_OPEN open64
+#define GNAT_STAT stat64
+#define GNAT_FSTAT fstat64
+#define GNAT_LSTAT lstat64
+#define GNAT_STRUCT_STAT struct stat64
+
+/* Type corresponding to GNAT.OS_Lib.OS_Time */
+typedef long OS_Time;
+
+#define __int64 long long
+
+/* A lazy cache for the attributes of a file. On some systems, a single call to
+ stat() will give all this information, so it is better than doing a system
+ call every time. On other systems this require several system calls.
+*/
+
+struct file_attributes {
+ int error;
+ /* Errno value returned by stat()/fstat(). If non-zero, other fields should
+ * be considered as invalid.
+ */
+
+ unsigned char exists;
+
+ unsigned char writable;
+ unsigned char readable;
+ unsigned char executable;
+
+ unsigned char symbolic_link;
+ unsigned char regular;
+ unsigned char directory;
+
+ OS_Time timestamp;
+ __int64 file_length;
+};
+/* WARNING: changing the size here might require changing the constant
+ * File_Attributes_Size in osint.ads (which should be big enough to
+ * fit the above struct on any system)
+ */
+
+extern int __gnat_max_path_len;
+extern OS_Time __gnat_current_time (void);
+extern void __gnat_current_time_string (uintptr_t);
+extern void __gnat_to_gm_time (uintptr_t, uintptr_t,
+ uintptr_t, uintptr_t,
+ uintptr_t, uintptr_t,
+ uintptr_t);
+extern void __gnat_to_os_time (uintptr_t, int, int,
+ int, int, int, int);
+extern int __gnat_get_maximum_file_name_length (void);
+extern int __gnat_get_switches_case_sensitive (void);
+extern int __gnat_get_file_names_case_sensitive (void);
+extern int __gnat_get_env_vars_case_sensitive (void);
+extern char __gnat_get_default_identifier_character_set (void);
+extern void __gnat_get_current_dir (uintptr_t, uintptr_t);
+extern void __gnat_get_object_suffix_ptr (uintptr_t, uintptr_t);
+extern void __gnat_get_executable_suffix_ptr (uintptr_t, uintptr_t);
+extern void __gnat_get_debuggable_suffix_ptr (uintptr_t, uintptr_t);
+extern int __gnat_readlink (uintptr_t, uintptr_t,
+ size_t);
+extern int __gnat_symlink (uintptr_t, uintptr_t);
+extern int __gnat_try_lock (uintptr_t, uintptr_t);
+extern int __gnat_open_new (uintptr_t, int);
+extern int __gnat_open_new_temp (uintptr_t, int);
+extern int __gnat_mkdir (uintptr_t, int);
+extern int __gnat_unlink (uintptr_t);
+extern int __gnat_rename (uintptr_t, uintptr_t);
+extern int __gnat_chdir (uintptr_t);
+extern int __gnat_rmdir (uintptr_t);
+
+extern FILE *__gnat_fopen (uintptr_t, uintptr_t,
+ int);
+extern FILE *__gnat_freopen (uintptr_t, uintptr_t,
+ uintptr_t, int);
+extern int __gnat_open (uintptr_t, int);
+extern int __gnat_open_read (uintptr_t, int);
+extern int __gnat_open_rw (uintptr_t, int);
+extern int __gnat_open_create (uintptr_t, int);
+extern int __gnat_create_output_file (uintptr_t);
+extern int __gnat_create_output_file_new (uintptr_t);
+
+extern int __gnat_open_append (uintptr_t, int);
+extern long __gnat_file_length_long (int);
+extern __int64 __gnat_file_length (int);
+extern __int64 __gnat_named_file_length (uintptr_t);
+extern void __gnat_tmp_name (uintptr_t);
+extern DIR *__gnat_opendir (uintptr_t);
+extern char *__gnat_readdir (uintptr_t, uintptr_t,
+ uintptr_t);
+extern int __gnat_closedir (uintptr_t);
+extern int __gnat_readdir_is_thread_safe (void);
+
+extern OS_Time __gnat_file_time_name (uintptr_t);
+extern OS_Time __gnat_file_time_fd (int);
+/* return -1 in case of error */
+
+extern void __gnat_set_file_time_name (uintptr_t, time_t);
+
+extern int __gnat_dup (int);
+extern int __gnat_dup2 (int, int);
+extern int __gnat_file_exists (uintptr_t);
+extern int __gnat_is_regular_file (uintptr_t);
+extern int __gnat_is_absolute_path (uintptr_t, int);
+extern int __gnat_is_directory (uintptr_t);
+extern int __gnat_is_writable_file (uintptr_t);
+extern int __gnat_is_readable_file (uintptr_t);
+extern int __gnat_is_executable_file (uintptr_t);
+
+extern void __gnat_reset_attributes (uintptr_t);
+extern int __gnat_error_attributes (uintptr_t);
+extern __int64 __gnat_file_length_attr (int, uintptr_t,
+ uintptr_t);
+extern OS_Time __gnat_file_time_name_attr (uintptr_t, uintptr_t);
+extern int __gnat_file_exists_attr (uintptr_t, uintptr_t);
+extern int __gnat_is_regular_file_attr (uintptr_t, uintptr_t);
+extern int __gnat_is_directory_attr (uintptr_t, uintptr_t);
+extern int __gnat_is_readable_file_attr (uintptr_t, uintptr_t);
+extern int __gnat_is_writable_file_attr (uintptr_t, uintptr_t);
+extern int __gnat_is_executable_file_attr (uintptr_t, uintptr_t);
+extern int __gnat_is_symbolic_link_attr (uintptr_t, uintptr_t);
+
+extern void __gnat_set_non_writable (uintptr_t);
+extern void __gnat_set_writable (uintptr_t);
+extern void __gnat_set_executable (uintptr_t, int);
+extern void __gnat_set_readable (uintptr_t);
+extern void __gnat_set_non_readable (uintptr_t);
+extern int __gnat_is_symbolic_link (uintptr_t);
+extern int __gnat_portable_spawn (uintptr_t);
+extern int __gnat_portable_no_block_spawn (uintptr_t);
+extern int __gnat_portable_wait (uintptr_t);
+extern char *__gnat_locate_exec (uintptr_t, uintptr_t);
+extern char *__gnat_locate_exec_on_path (uintptr_t);
+extern char *__gnat_locate_regular_file (uintptr_t, uintptr_t);
+extern void __gnat_maybe_glob_args (uintptr_t, uintptr_t);
+extern void __gnat_os_exit (int);
+extern char *__gnat_get_libraries_from_registry (void);
+extern int __gnat_to_canonical_file_list_init (uintptr_t, int);
+extern char *__gnat_to_canonical_file_list_next (void);
+extern void __gnat_to_canonical_file_list_free (void);
+extern char *__gnat_to_canonical_dir_spec (uintptr_t, int);
+extern char *__gnat_to_canonical_file_spec (uintptr_t);
+extern char *__gnat_to_host_dir_spec (uintptr_t, int);
+extern char *__gnat_to_host_file_spec (uintptr_t);
+extern char *__gnat_to_canonical_path_spec (uintptr_t);
+extern void __gnat_adjust_os_resource_limits (void);
+extern void convert_addresses (uintptr_t, uintptr_t,
+ int, uintptr_t,
+ uintptr_t);
+extern int __gnat_copy_attribs (uintptr_t, uintptr_t,
+ int);
+extern int __gnat_feof (uintptr_t);
+extern int __gnat_ferror (uintptr_t);
+extern int __gnat_fileno (uintptr_t);
+extern int __gnat_is_regular_file_fd (int);
+extern FILE *__gnat_constant_stderr (void);
+extern FILE *__gnat_constant_stdin (void);
+extern FILE *__gnat_constant_stdout (void);
+extern char *__gnat_full_name (uintptr_t, uintptr_t);
+
+extern int __gnat_arg_count (void);
+extern int __gnat_len_arg (int);
+extern void __gnat_fill_arg (uintptr_t, int);
+extern int __gnat_env_count (void);
+extern int __gnat_len_env (int);
+extern void __gnat_fill_env (uintptr_t, int);
+
+/* Routines for interface to scanf and printf functions for integer values */
+
+extern int get_int (void);
+extern void put_int (int);
+extern void put_int_stderr (int);
+extern int get_char (void);
+extern void put_char (int);
+extern void put_char_stderr (int);
+
+extern void __gnat_set_exit_status (int);
+
+extern int __gnat_expect_fork (void);
+extern void __gnat_expect_portable_execvp (uintptr_t, uintptr_t);
+extern int __gnat_pipe (uintptr_t);
+extern int __gnat_expect_poll (uintptr_t, int, int,
+ uintptr_t);
+extern void __gnat_set_binary_mode (int);
+extern void __gnat_set_text_mode (int);
+extern void __gnat_set_mode (int,int);
+extern char *__gnat_ttyname (int);
+extern int __gnat_lseek (int, long, int);
+extern int __gnat_set_close_on_exec (int, int);
+extern int __gnat_dup (int);
+extern int __gnat_dup2 (int, int);
+
+/* large file support */
+extern __int64 __gnat_ftell64 (uintptr_t);
+extern int __gnat_fseek64 (uintptr_t, __int64, int);
+
+extern int __gnat_number_of_cpus (void);
+
+extern void __gnat_os_filename (uintptr_t, uintptr_t,
+ uintptr_t, uintptr_t,
+ uintptr_t, uintptr_t);
+
+extern size_t __gnat_strlen (uintptr_t);
+extern char * __gnat_strncpy (uintptr_t, uintptr_t,
+ size_t);
+extern int __gnat_atoi (uintptr_t);
+extern void __gnat_clearerr (uintptr_t);
+extern int __gnat_fclose (uintptr_t);
+extern FILE * __gnat_fdopen (int, uintptr_t);
+extern int __gnat_fflush (uintptr_t);
+extern int __gnat_fgetc (uintptr_t);
+extern char * __gnat_fgets (uintptr_t, int,
+ uintptr_t);
+extern int __gnat_fputc (int, uintptr_t);
+extern int __gnat_fputs (uintptr_t, uintptr_t);
+extern int __gnat_fseek (uintptr_t, long, int);
+extern void * __gnat_memcpy (uintptr_t, uintptr_t,
+ size_t);
+extern void * __gnat_memmove (uintptr_t, uintptr_t,
+ size_t);
+extern char * __gnat_mktemp (uintptr_t);
+extern int __gnat_pclose (uintptr_t);
+extern FILE * __gnat_popen (uintptr_t, uintptr_t);
+extern void __gnat_rewind (uintptr_t);
+extern int __gnat_setvbuf (uintptr_t, uintptr_t,
+ int, size_t);
+extern char * __gnat_tmpnam (uintptr_t);
+extern int __gnat_ungetc (int, uintptr_t);
+extern ssize_t __gnat_read (int, uintptr_t, size_t);
+extern ssize_t __gnat_write (int, uintptr_t, size_t);
+
+extern char * __gnat_x32_getenv (uintptr_t);
+extern void * __gnat_x32_realloc (uintptr_t, size_t);
+extern void __gnat_x32_free (uintptr_t);
+
+extern void *__gnat_lwp_self (void);
+
+/* Routines for interface to required CPU set primitives */
+#include <sched.h>
+
+extern cpu_set_t *__gnat_cpu_alloc (size_t);
+extern size_t __gnat_cpu_alloc_size (size_t);
+extern void __gnat_cpu_free (uintptr_t);
+extern void __gnat_cpu_zero (size_t, uintptr_t);
+extern void __gnat_cpu_set (int, size_t, uintptr_t);
+
+#ifdef IN_RTS
+/* Portable definition of strdup, which is not available on all systems. */
+#define xstrdup(S) strcpy ((char *) malloc (strlen (S) + 1), S)
+#endif
+
+/* This function returns the version of GCC being used. Here it's GCC 3. */
+extern int get_gcc_version (void);
+
+extern int __gnat_binder_supports_auto_init (void);
+extern int __gnat_sals_init_using_constructors (void);
+
+extern const void * __gnat_get_executable_load_address (void);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/ada/argv-x32.c b/gcc/ada/argv-x32.c
new file mode 100644
index 00000000000..6de1e512a49
--- /dev/null
+++ b/gcc/ada/argv-x32.c
@@ -0,0 +1,123 @@
+/****************************************************************************
+ * *
+ * GNAT COMPILER COMPONENTS *
+ * *
+ * A R G V *
+ * *
+ * C Implementation File *
+ * *
+ * Copyright (C) 2015, Free Software Foundation, Inc. *
+ * *
+ * 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 3, 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. *
+ * *
+ * As a special exception under Section 7 of GPL version 3, you are granted *
+ * additional permissions described in the GCC Runtime Library Exception, *
+ * version 3.1, as published by the Free Software Foundation. *
+ * *
+ * You should have received a copy of the GNU General Public License and *
+ * a copy of the GCC Runtime Library Exception along with this program; *
+ * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see *
+ * <http://www.gnu.org/licenses/>. *
+ * *
+ * GNAT was originally developed by the GNAT team at New York University. *
+ * Extensive contributions were provided by Ada Core Technologies Inc. *
+ * *
+ ****************************************************************************/
+
+/* Routines for accessing command line arguments from both the runtime
+ library and from the compiler itself. In the former case, gnat_argc
+ and gnat_argv are the original argc and argv values as stored by the
+ binder generated main program, and these routines are accessed from
+ the Ada.Command_Line package. In the compiler case, gnat_argc and
+ gnat_argv are the values as modified by toplev, and these routines
+ are accessed from the Osint package. */
+
+/* Also routines for accessing the environment from the runtime library.
+ Gnat_envp is the original envp value as stored by the binder generated
+ main program, and these routines are accessed from the
+ Ada.Command_Line.Environment package. */
+
+#if !defined __linux__ && !defined __x86_64__ && !defined __ILP32__
+#error Unsupported platform.
+#endif
+
+#ifdef IN_RTS
+#include "tconfig.h"
+#include "tsystem.h"
+#include <sys/stat.h>
+#else
+#include "config.h"
+#include "system.h"
+#endif
+
+#include "adaint.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* argc and argv of the main program are saved under gnat_argc and gnat_argv,
+ envp of the main program is saved under gnat_envp. */
+
+int gnat_argc = 0;
+const char **gnat_argv = (const char **) 0;
+const char **gnat_envp = (const char **) 0;
+
+int
+__gnat_arg_count (void)
+{
+ return gnat_argc;
+}
+
+int
+__gnat_len_arg (int arg_num)
+{
+ if (gnat_argv != NULL)
+ return strlen (gnat_argv[arg_num]);
+ else
+ return 0;
+}
+
+void
+__gnat_fill_arg (uintptr_t a_p, int i)
+{
+ char *a = (char *) a_p;
+ if (gnat_argv != NULL)
+ strncpy (a, gnat_argv[i], strlen(gnat_argv[i]));
+}
+
+int
+__gnat_env_count (void)
+{
+ int i;
+
+ for (i = 0; gnat_envp[i]; i++)
+ ;
+ return i;
+}
+
+int
+__gnat_len_env (int env_num)
+{
+ if (gnat_envp != NULL)
+ return strlen (gnat_envp[env_num]);
+ else
+ return 0;
+}
+
+void
+__gnat_fill_env (uintptr_t a_p, int i)
+{
+ char *a = (char *) a_p;
+ if (gnat_envp != NULL)
+ strncpy (a, gnat_envp[i], strlen (gnat_envp[i]));
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/ada/cstreams-x32.c b/gcc/ada/cstreams-x32.c
new file mode 100644
index 00000000000..5e8b80e329c
--- /dev/null
+++ b/gcc/ada/cstreams-x32.c
@@ -0,0 +1,224 @@
+/****************************************************************************
+ * *
+ * GNAT RUN-TIME COMPONENTS *
+ * *
+ * C S T R E A M S *
+ * *
+ * Auxiliary C functions for Interfaces.C.Streams *
+ * *
+ * Copyright (C) 2015, Free Software Foundation, Inc. *
+ * *
+ * 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 3, 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. *
+ * *
+ * As a special exception under Section 7 of GPL version 3, you are granted *
+ * additional permissions described in the GCC Runtime Library Exception, *
+ * version 3.1, as published by the Free Software Foundation. *
+ * *
+ * You should have received a copy of the GNU General Public License and *
+ * a copy of the GCC Runtime Library Exception along with this program; *
+ * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see *
+ * <http://www.gnu.org/licenses/>. *
+ * *
+ * GNAT was originally developed by the GNAT team at New York University. *
+ * Extensive contributions were provided by Ada Core Technologies Inc. *
+ * *
+ ****************************************************************************/
+
+/* Routines required for implementing routines in Interfaces.C.Streams. */
+
+#if !defined __linux__ && !defined __x86_64__ && !defined __ILP32__
+#error Unsupported platform.
+#endif
+
+#ifndef _LARGEFILE_SOURCE
+#define _LARGEFILE_SOURCE
+#endif
+#define _FILE_OFFSET_BITS 64
+/* the define above will make off_t a 64bit type on GNU/Linux */
+
+#include <stdio.h>
+#include <sys/types.h>
+
+#ifdef IN_RTS
+#include "tconfig.h"
+#include "tsystem.h"
+#include <sys/stat.h>
+#else
+#include "config.h"
+#include "system.h"
+#endif
+
+#include "adaint.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef linux
+/* Don't use macros on GNU/Linux since they cause incompatible changes between
+ glibc 2.0 and 2.1 */
+
+#ifdef stderr
+# undef stderr
+#endif
+#ifdef stdin
+# undef stdin
+#endif
+#ifdef stdout
+# undef stdout
+#endif
+
+#endif
+
+int
+__gnat_feof (uintptr_t stream_p)
+{
+ FILE *stream = (FILE *)stream_p;
+ return (feof (stream));
+}
+
+int
+__gnat_ferror (uintptr_t stream_p)
+{
+ FILE *stream = (FILE *)stream_p;
+ return (ferror (stream));
+}
+
+int
+__gnat_fileno (uintptr_t stream_p)
+{
+ FILE *stream = (FILE *)stream_p;
+ return (fileno (stream));
+}
+
+/* on some systems, the constants for seek are not defined, if so, then
+ provide the conventional definitions */
+
+#ifndef SEEK_SET
+#define SEEK_SET 0 /* Set file pointer to offset */
+#define SEEK_CUR 1 /* Set file pointer to its current value plus offset */
+#define SEEK_END 2 /* Set file pointer to the size of the file plus offset */
+#endif
+
+/* if L_tmpnam is not set, use a large number that should be safe */
+#ifndef L_tmpnam
+#define L_tmpnam 256
+#endif
+
+int __gnat_constant_eof = EOF;
+int __gnat_constant_iofbf = _IOFBF;
+int __gnat_constant_iolbf = _IOLBF;
+int __gnat_constant_ionbf = _IONBF;
+int __gnat_constant_l_tmpnam = L_tmpnam;
+int __gnat_constant_seek_cur = SEEK_CUR;
+int __gnat_constant_seek_end = SEEK_END;
+int __gnat_constant_seek_set = SEEK_SET;
+
+FILE *
+__gnat_constant_stderr (void)
+{
+ return stderr;
+}
+
+FILE *
+__gnat_constant_stdin (void)
+{
+ return stdin;
+}
+
+FILE *
+__gnat_constant_stdout (void)
+{
+ return stdout;
+}
+
+char *
+__gnat_full_name (uintptr_t nam_p, uintptr_t buffer_p)
+{
+ char *nam = (char *)nam_p;
+ char *buffer = (char *)buffer_p;
+
+ /* Use realpath function which resolves links and references to . and ..
+ on those Unix systems that support it. Note that GNU/Linux provides it but
+ cannot handle more than 5 symbolic links in a full name, so we use the
+ getcwd approach instead. */
+ realpath (nam, buffer);
+ if (nam[0] != '/')
+ {
+ char *p = getcwd (buffer, __gnat_max_path_len);
+
+ if (p == 0)
+ {
+ buffer[0] = '\0';
+ return 0;
+ }
+
+
+ /* If the name returned is an absolute path, it is safe to append '/'
+ to the path and concatenate the name of the file. */
+ if (buffer[0] == '/')
+ strcat (buffer, "/");
+
+ strcat (buffer, nam);
+ }
+ else
+ strcpy (buffer, nam);
+
+ return buffer;
+}
+
+#if defined(linux) || defined(sun) \
+ || defined (__FreeBSD__) || defined(__APPLE__)
+/* section for platforms having ftello/fseeko */
+
+__int64
+__gnat_ftell64 (uintptr_t stream_p)
+{
+ FILE *stream = (FILE *)stream_p;
+ return (__int64)ftello (stream);
+}
+
+int
+__gnat_fseek64 (uintptr_t stream_p, __int64 offset, int origin)
+{
+ FILE *stream = (FILE *)stream_p;
+ /* make sure that the offset is not bigger than the OS off_t, if so return
+ with error as this mean that we are trying to handle files larger than
+ 2Gb on a patform not supporting it. */
+ if ((off_t)offset == offset)
+ return fseeko (stream, (off_t) offset, origin);
+ else
+ return -1;
+}
+
+#else
+
+__int64
+__gnat_ftell64 (uintptr_t stream_p)
+{
+ FILE *stream = (FILE *)stream_p;
+ return (__int64)ftell (stream);
+}
+
+int
+__gnat_fseek64 (uintptr_t stream_p, __int64 offset, int origin)
+{
+ FILE *stream = (FILE *)stream_p;
+ /* make sure that the offset is not bigger than the OS off_t, if so return
+ with error as this mean that we are trying to handle files larger than
+ 2Gb on a patform not supporting it. */
+ if ((off_t)offset == offset)
+ return fseek (stream, (off_t) offset, origin);
+ else
+ return -1;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/ada/gcc-interface/Makefile.in b/gcc/ada/gcc-interface/Makefile.in
index 48bf47ccf04..b91e43033dc 100644
--- a/gcc/ada/gcc-interface/Makefile.in
+++ b/gcc/ada/gcc-interface/Makefile.in
@@ -2237,6 +2237,13 @@ ifeq ($(strip $(filter-out %x32 linux%,$(target_cpu) $(target_os))),)
s-inmaop.adb<s-inmaop-posix.adb \
s-intman.adb<s-intman-posix.adb \
s-linux.ads<s-linux-x32.ads \
+ s-crtl.ads<s-crtl-x32.ads \
+ adaint.c<adaint-x32.c \
+ adaint.h<adaint-x32.h \
+ argv.c<argv-x32.c \
+ cstreams.c<cstreams-x32.c \
+ init.c<init-x32.c \
+ mkdir.c<mkdir-x32.c \
s-mudido.adb<s-mudido-affinity.adb \
s-osinte.ads<s-osinte-linux.ads \
s-osinte.adb<s-osinte-x32.adb \
diff --git a/gcc/ada/init-x32.c b/gcc/ada/init-x32.c
new file mode 100644
index 00000000000..f195fa61a18
--- /dev/null
+++ b/gcc/ada/init-x32.c
@@ -0,0 +1,651 @@
+/****************************************************************************
+ * *
+ * GNAT COMPILER COMPONENTS *
+ * *
+ * I N I T *
+ * *
+ * C Implementation File *
+ * *
+ * Copyright (C) 2015, Free Software Foundation, Inc. *
+ * *
+ * 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 3, 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. *
+ * *
+ * As a special exception under Section 7 of GPL version 3, you are granted *
+ * additional permissions described in the GCC Runtime Library Exception, *
+ * version 3.1, as published by the Free Software Foundation. *
+ * *
+ * You should have received a copy of the GNU General Public License and *
+ * a copy of the GCC Runtime Library Exception along with this program; *
+ * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see *
+ * <http://www.gnu.org/licenses/>. *
+ * *
+ * GNAT was originally developed by the GNAT team at New York University. *
+ * Extensive contributions were provided by Ada Core Technologies Inc. *
+ * *
+ ****************************************************************************/
+
+/* This unit contains initialization circuits that are system dependent.
+ A major part of the functionality involves stack overflow checking.
+ The GCC backend generates probe instructions to test for stack overflow.
+ For details on the exact approach used to generate these probes, see the
+ "Using and Porting GCC" manual, in particular the "Stack Checking" section
+ and the subsection "Specifying How Stack Checking is Done". The handlers
+ installed by this file are used to catch the resulting signals that come
+ from these probes failing (i.e. touching protected pages). */
+
+/* This file should be kept synchronized with s-init.ads, s-init.adb and the
+ s-init-*.adb variants. All these files implement the required functionality
+ for different targets. */
+
+#if !defined (__linux__)
+#error Unsupported platform.
+#endif
+
+/* The following include is here to meet the published VxWorks requirement
+ that the __vxworks header appear before any other include. */
+#ifdef __vxworks
+#include "vxWorks.h"
+#endif
+
+#ifdef __ANDROID__
+#undef linux
+#endif
+
+#ifdef IN_RTS
+#include "tconfig.h"
+#include "tsystem.h"
+#include <sys/stat.h>
+
+/* We don't have libiberty, so use malloc. */
+#define xmalloc(S) malloc (S)
+#else
+#include "config.h"
+#include "system.h"
+#endif
+
+#include "adaint.h"
+#include "raise.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void __gnat_raise_program_error (const char *, int);
+
+/* Addresses of exception data blocks for predefined exceptions. Tasking_Error
+ is not used in this unit, and the abort signal is only used on IRIX.
+ ??? Revisit this part since IRIX is no longer supported. */
+extern struct Exception_Data constraint_error;
+extern struct Exception_Data numeric_error;
+extern struct Exception_Data program_error;
+extern struct Exception_Data storage_error;
+
+/* For the Cert run time we use the regular raise exception routine because
+ Raise_From_Signal_Handler is not available. */
+#ifdef CERT
+#define Raise_From_Signal_Handler \
+ __gnat_raise_exception
+extern void Raise_From_Signal_Handler (struct Exception_Data *, const char *);
+#else
+#define Raise_From_Signal_Handler \
+ ada__exceptions__raise_from_signal_handler
+extern void Raise_From_Signal_Handler (struct Exception_Data *, const char *);
+#endif
+
+/* Global values computed by the binder. */
+int __gl_main_priority = -1;
+int __gl_main_cpu = -1;
+int __gl_time_slice_val = -1;
+char __gl_wc_encoding = 'n';
+char __gl_locking_policy = ' ';
+char __gl_queuing_policy = ' ';
+char __gl_task_dispatching_policy = ' ';
+char *__gl_priority_specific_dispatching = 0;
+int __gl_num_specific_dispatching = 0;
+char *__gl_interrupt_states = 0;
+int __gl_num_interrupt_states = 0;
+int __gl_unreserve_all_interrupts = 0;
+int __gl_exception_tracebacks = 0;
+int __gl_detect_blocking = 0;
+int __gl_default_stack_size = -1;
+int __gl_leap_seconds_support = 0;
+int __gl_canonical_streams = 0;
+
+/* This value is not used anymore, but kept for bootstrapping purpose. */
+int __gl_zero_cost_exceptions = 0;
+
+/* Indication of whether synchronous signal handler has already been
+ installed by a previous call to adainit. */
+int __gnat_handler_installed = 0;
+
+#ifndef IN_RTS
+int __gnat_inside_elab_final_code = 0;
+/* ??? This variable is obsolete since 2001-08-29 but is kept to allow
+ bootstrap from old GNAT versions (< 3.15). */
+#endif
+
+/* HAVE_GNAT_INIT_FLOAT must be set on every targets where a __gnat_init_float
+ is defined. If this is not set then a void implementation will be defined
+ at the end of this unit. */
+#undef HAVE_GNAT_INIT_FLOAT
+
+/******************************/
+/* __gnat_get_interrupt_state */
+/******************************/
+
+char __gnat_get_interrupt_state (int);
+
+/* This routine is called from the runtime as needed to determine the state
+ of an interrupt, as set by an Interrupt_State pragma appearing anywhere
+ in the current partition. The input argument is the interrupt number,
+ and the result is one of the following:
+
+ 'n' this interrupt not set by any Interrupt_State pragma
+ 'u' Interrupt_State pragma set state to User
+ 'r' Interrupt_State pragma set state to Runtime
+ 's' Interrupt_State pragma set state to System */
+
+char
+__gnat_get_interrupt_state (int intrup)
+{
+ if (intrup >= __gl_num_interrupt_states)
+ return 'n';
+ else
+ return __gl_interrupt_states [intrup];
+}
+
+/***********************************/
+/* __gnat_get_specific_dispatching */
+/***********************************/
+
+char __gnat_get_specific_dispatching (int);
+
+/* This routine is called from the runtime as needed to determine the
+ priority specific dispatching policy, as set by a
+ Priority_Specific_Dispatching pragma appearing anywhere in the current
+ partition. The input argument is the priority number, and the result
+ is the upper case first character of the policy name, e.g. 'F' for
+ FIFO_Within_Priorities. A space ' ' is returned if no
+ Priority_Specific_Dispatching pragma is used in the partition. */
+
+char
+__gnat_get_specific_dispatching (int priority)
+{
+ if (__gl_num_specific_dispatching == 0)
+ return ' ';
+ else if (priority >= __gl_num_specific_dispatching)
+ return 'F';
+ else
+ return __gl_priority_specific_dispatching [priority];
+}
+
+#ifndef IN_RTS
+
+/**********************/
+/* __gnat_set_globals */
+/**********************/
+
+/* This routine is kept for bootstrapping purposes, since the binder generated
+ file now sets the __gl_* variables directly. */
+
+void
+__gnat_set_globals (void)
+{
+}
+
+#endif
+
+/*********************/
+/* GNU/Linux Section */
+/*********************/
+
+#if defined (linux)
+
+#include <signal.h>
+
+#define __USE_GNU 1 /* required to get REG_EIP/RIP from glibc's ucontext.h */
+#include <sys/ucontext.h>
+
+/* GNU/Linux, which uses glibc, does not define NULL in included
+ header files. */
+
+#if !defined (NULL)
+#define NULL ((void *) 0)
+#endif
+
+#if defined (MaRTE)
+
+/* MaRTE OS provides its own version of sigaction, sigfillset, and
+ sigemptyset (overriding these symbol names). We want to make sure that
+ the versions provided by the underlying C library are used here (these
+ versions are renamed by MaRTE to linux_sigaction, fake_linux_sigfillset,
+ and fake_linux_sigemptyset, respectively). The MaRTE library will not
+ always be present (it will not be linked if no tasking constructs are
+ used), so we use the weak symbol mechanism to point always to the symbols
+ defined within the C library. */
+
+#pragma weak linux_sigaction
+int linux_sigaction (int signum, const struct sigaction *act,
+ struct sigaction *oldact)
+{
+ return sigaction (signum, act, oldact);
+}
+#define sigaction(signum, act, oldact) linux_sigaction (signum, act, oldact)
+
+#pragma weak fake_linux_sigfillset
+void fake_linux_sigfillset (sigset_t *set)
+{
+ sigfillset (set);
+}
+#define sigfillset(set) fake_linux_sigfillset (set)
+
+#pragma weak fake_linux_sigemptyset
+void fake_linux_sigemptyset (sigset_t *set)
+{
+ sigemptyset (set);
+}
+#define sigemptyset(set) fake_linux_sigemptyset (set)
+
+#endif
+
+#if defined (i386) || defined (__x86_64__) || defined (__ia64__) \
+ || defined (__ARMEL__)
+
+#define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
+
+void
+__gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
+{
+ mcontext_t *mcontext = &((ucontext_t *) ucontext)->uc_mcontext;
+
+ /* On the i386 and x86-64 architectures, stack checking is performed by
+ means of probes with moving stack pointer, that is to say the probed
+ address is always the value of the stack pointer. Upon hitting the
+ guard page, the stack pointer therefore points to an inaccessible
+ address and an alternate signal stack is needed to run the handler.
+ But there is an additional twist: on these architectures, the EH
+ return code writes the address of the handler at the target CFA's
+ value on the stack before doing the jump. As a consequence, if
+ there is an active handler in the frame whose stack has overflowed,
+ the stack pointer must nevertheless point to an accessible address
+ by the time the EH return is executed.
+
+ We therefore adjust the saved value of the stack pointer by the size
+ of one page + a small dope of 4 words, in order to make sure that it
+ points to an accessible address in case it's used as the target CFA.
+ The stack checking code guarantees that this address is unused by the
+ time this happens. */
+
+#if defined (i386)
+ unsigned long *pc = (unsigned long *)mcontext->gregs[REG_EIP];
+ /* The pattern is "orl $0x0,(%esp)" for a probe in 32-bit mode. */
+ if (signo == SIGSEGV && pc && *pc == 0x00240c83)
+ mcontext->gregs[REG_ESP] += 4096 + 4 * sizeof (unsigned long);
+#elif defined (__x86_64__)
+ unsigned long long *pc = (unsigned long long *)mcontext->gregs[REG_RIP];
+ if (signo == SIGSEGV && pc
+ /* The pattern is "orq $0x0,(%rsp)" for a probe in 64-bit mode. */
+ && ((*pc & 0xffffffffffLL) == 0x00240c8348LL
+ /* The pattern may also be "orl $0x0,(%esp)" for a probe in
+ x32 mode. */
+ || (*pc & 0xffffffffLL) == 0x00240c83LL))
+ mcontext->gregs[REG_RSP] += 4096 + 4 * sizeof (unsigned long);
+#elif defined (__ia64__)
+ /* ??? The IA-64 unwinder doesn't compensate for signals. */
+ mcontext->sc_ip++;
+#elif defined (__ARMEL__)
+ /* ARM Bump has to be an even number because of odd/even architecture. */
+ mcontext->arm_pc+=2;
+#endif
+}
+
+#endif
+
+static void
+__gnat_error_handler (int sig, siginfo_t *si ATTRIBUTE_UNUSED, void *ucontext)
+{
+ struct Exception_Data *exception;
+ const char *msg;
+
+ /* Adjusting is required for every fault context, so adjust for this one
+ now, before we possibly trigger a recursive fault below. */
+ __gnat_adjust_context_for_raise (sig, ucontext);
+
+ switch (sig)
+ {
+ case SIGSEGV:
+ /* Here we would like a discrimination test to see whether the page
+ before the faulting address is accessible. Unfortunately, Linux
+ seems to have no way of giving us the faulting address.
+
+ In old versions of init.c, we had a test of the page before the
+ stack pointer:
+
+ ((volatile char *)
+ ((long) si->esp_at_signal & - getpagesize ()))[getpagesize ()];
+
+ but that's wrong since it tests the stack pointer location and the
+ stack probing code may not move it until all probes succeed.
+
+ For now we simply do not attempt any discrimination at all. Note
+ that this is quite acceptable, since a "real" SIGSEGV can only
+ occur as the result of an erroneous program. */
+ exception = &storage_error;
+ msg = "stack overflow or erroneous memory access";
+ break;
+
+ case SIGBUS:
+ exception = &storage_error;
+ msg = "SIGBUS: possible stack overflow";
+ break;
+
+ case SIGFPE:
+ exception = &constraint_error;
+ msg = "SIGFPE";
+ break;
+
+ default:
+ exception = &program_error;
+ msg = "unhandled signal";
+ }
+
+ Raise_From_Signal_Handler (exception, msg);
+}
+
+#ifndef __ia64__
+#define HAVE_GNAT_ALTERNATE_STACK 1
+/* This must be in keeping with System.OS_Interface.Alternate_Stack_Size.
+ It must be larger than MINSIGSTKSZ and hopefully near 2 * SIGSTKSZ. */
+# if 16 * 1024 < MINSIGSTKSZ
+# error "__gnat_alternate_stack too small"
+# endif
+char __gnat_alternate_stack[16 * 1024];
+#endif
+
+#ifdef __XENO__
+#include <sys/mman.h>
+#include <native/task.h>
+
+RT_TASK main_task;
+#endif
+
+void
+__gnat_install_handler (void)
+{
+ struct sigaction act;
+
+#ifdef __XENO__
+ int prio;
+
+ if (__gl_main_priority == -1)
+ prio = 49;
+ else
+ prio = __gl_main_priority;
+
+ /* Avoid memory swapping for this program */
+
+ mlockall (MCL_CURRENT|MCL_FUTURE);
+
+ /* Turn the current Linux task into a native Xenomai task */
+
+ rt_task_shadow (&main_task, "environment_task", prio, T_FPU);
+#endif
+
+ /* Set up signal handler to map synchronous signals to appropriate
+ exceptions. Make sure that the handler isn't interrupted by another
+ signal that might cause a scheduling event! Also setup an alternate
+ stack region for the handler execution so that stack overflows can be
+ handled properly, avoiding a SEGV generation from stack usage by the
+ handler itself. */
+
+ act.sa_sigaction = __gnat_error_handler;
+ act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
+ sigemptyset (&act.sa_mask);
+
+ /* Do not install handlers if interrupt state is "System". */
+ if (__gnat_get_interrupt_state (SIGABRT) != 's')
+ sigaction (SIGABRT, &act, NULL);
+ if (__gnat_get_interrupt_state (SIGFPE) != 's')
+ sigaction (SIGFPE, &act, NULL);
+ if (__gnat_get_interrupt_state (SIGILL) != 's')
+ sigaction (SIGILL, &act, NULL);
+ if (__gnat_get_interrupt_state (SIGBUS) != 's')
+ sigaction (SIGBUS, &act, NULL);
+ if (__gnat_get_interrupt_state (SIGSEGV) != 's')
+ {
+#ifdef HAVE_GNAT_ALTERNATE_STACK
+ /* Setup an alternate stack region for the handler execution so that
+ stack overflows can be handled properly, avoiding a SEGV generation
+ from stack usage by the handler itself. */
+ stack_t stack;
+
+ stack.ss_sp = __gnat_alternate_stack;
+ stack.ss_size = sizeof (__gnat_alternate_stack);
+ stack.ss_flags = 0;
+ sigaltstack (&stack, NULL);
+
+ act.sa_flags |= SA_ONSTACK;
+#endif
+ sigaction (SIGSEGV, &act, NULL);
+ }
+
+ __gnat_handler_installed = 1;
+}
+
+#elif defined(__ANDROID__)
+
+/*******************/
+/* Android Section */
+/*******************/
+
+#include <signal.h>
+#include "sigtramp.h"
+
+#define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
+
+void
+__gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
+{
+ mcontext_t *mcontext = &((ucontext_t *) ucontext)->uc_mcontext;
+
+ /* ARM Bump has to be an even number because of odd/even architecture. */
+ ((mcontext_t *) mcontext)->arm_pc += 2;
+}
+
+static void
+__gnat_map_signal (int sig,
+ siginfo_t *si ATTRIBUTE_UNUSED,
+ void *ucontext ATTRIBUTE_UNUSED)
+{
+ struct Exception_Data *exception;
+ const char *msg;
+
+ switch (sig)
+ {
+ case SIGSEGV:
+ exception = &storage_error;
+ msg = "stack overflow or erroneous memory access";
+ break;
+
+ case SIGBUS:
+ exception = &constraint_error;
+ msg = "SIGBUS";
+ break;
+
+ case SIGFPE:
+ exception = &constraint_error;
+ msg = "SIGFPE";
+ break;
+
+ default:
+ exception = &program_error;
+ msg = "unhandled signal";
+ }
+
+ Raise_From_Signal_Handler (exception, msg);
+}
+
+static void
+__gnat_error_handler (int sig,
+ siginfo_t *si ATTRIBUTE_UNUSED,
+ void *ucontext ATTRIBUTE_UNUSED)
+{
+ __gnat_adjust_context_for_raise (sig, ucontext);
+
+ __gnat_sigtramp (sig, (void *) si, (void *) ucontext,
+ (__sigtramphandler_t *)&__gnat_map_signal);
+}
+
+/* This must be in keeping with System.OS_Interface.Alternate_Stack_Size. */
+char __gnat_alternate_stack[16 * 1024];
+
+void
+__gnat_install_handler (void)
+{
+ struct sigaction act;
+
+ /* Set up signal handler to map synchronous signals to appropriate
+ exceptions. Make sure that the handler isn't interrupted by another
+ signal that might cause a scheduling event! Also setup an alternate
+ stack region for the handler execution so that stack overflows can be
+ handled properly, avoiding a SEGV generation from stack usage by the
+ handler itself. */
+
+ stack_t stack;
+ stack.ss_sp = __gnat_alternate_stack;
+ stack.ss_size = sizeof (__gnat_alternate_stack);
+ stack.ss_flags = 0;
+ sigaltstack (&stack, NULL);
+
+ act.sa_sigaction = __gnat_error_handler;
+ act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
+ sigemptyset (&act.sa_mask);
+
+ sigaction (SIGABRT, &act, NULL);
+ sigaction (SIGFPE, &act, NULL);
+ sigaction (SIGILL, &act, NULL);
+ sigaction (SIGBUS, &act, NULL);
+ act.sa_flags |= SA_ONSTACK;
+ sigaction (SIGSEGV, &act, NULL);
+
+ __gnat_handler_installed = 1;
+}
+
+#else
+
+/* For all other versions of GNAT, the handler does nothing. */
+
+/*******************/
+/* Default Section */
+/*******************/
+
+void
+__gnat_install_handler (void)
+{
+ __gnat_handler_installed = 1;
+}
+
+#endif
+
+/*********************/
+/* __gnat_init_float */
+/*********************/
+
+/* This routine is called as each process thread is created, for possible
+ initialization of the FP processor. This version is used under INTERIX
+ and WIN32. */
+
+#if defined (_WIN32) || defined (__INTERIX) \
+ || defined (__Lynx__) || defined(__NetBSD__) || defined(__FreeBSD__) \
+ || defined (__OpenBSD__)
+
+#define HAVE_GNAT_INIT_FLOAT
+
+void
+__gnat_init_float (void)
+{
+#if defined (__i386__) || defined (i386) || defined (__x86_64)
+
+ /* This is used to properly initialize the FPU on an x86 for each
+ process thread. */
+
+ asm ("finit");
+
+#endif /* Defined __i386__ */
+}
+#endif
+
+#ifndef HAVE_GNAT_INIT_FLOAT
+
+/* All targets without a specific __gnat_init_float will use an empty one. */
+void
+__gnat_init_float (void)
+{
+}
+#endif
+
+/***********************************/
+/* __gnat_adjust_context_for_raise */
+/***********************************/
+
+#ifndef HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
+
+/* All targets without a specific version will use an empty one. */
+
+/* Given UCONTEXT a pointer to a context structure received by a signal
+ handler for SIGNO, perform the necessary adjustments to let the handler
+ raise an exception. Calls to this routine are not conditioned by the
+ propagation scheme in use. */
+
+void
+__gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED,
+ void *ucontext ATTRIBUTE_UNUSED)
+{
+ /* We used to compensate here for the raised from call vs raised from signal
+ exception discrepancy with the GCC ZCX scheme, but this now can be dealt
+ with generically in the unwinder (see GCC PR other/26208). This however
+ requires the use of the _Unwind_GetIPInfo routine in raise-gcc.c, which
+ is predicated on the definition of HAVE_GETIPINFO at compile time. Only
+ the VMS ports still do the compensation described in the few lines below.
+
+ *** Call vs signal exception discrepancy with GCC ZCX scheme ***
+
+ The GCC unwinder expects to be dealing with call return addresses, since
+ this is the "nominal" case of what we retrieve while unwinding a regular
+ call chain.
+
+ To evaluate if a handler applies at some point identified by a return
+ address, the propagation engine needs to determine what region the
+ corresponding call instruction pertains to. Because the return address
+ may not be attached to the same region as the call, the unwinder always
+ subtracts "some" amount from a return address to search the region
+ tables, amount chosen to ensure that the resulting address is inside the
+ call instruction.
+
+ When we raise an exception from a signal handler, e.g. to transform a
+ SIGSEGV into Storage_Error, things need to appear as if the signal
+ handler had been "called" by the instruction which triggered the signal,
+ so that exception handlers that apply there are considered. What the
+ unwinder will retrieve as the return address from the signal handler is
+ what it will find as the faulting instruction address in the signal
+ context pushed by the kernel. Leaving this address untouched looses, if
+ the triggering instruction happens to be the very first of a region, as
+ the later adjustments performed by the unwinder would yield an address
+ outside that region. We need to compensate for the unwinder adjustments
+ at some point, and this is what this routine is expected to do.
+
+ signo is passed because on some targets for some signals the PC in
+ context points to the instruction after the faulting one, in which case
+ the unwinder adjustment is still desired. */
+}
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/ada/mkdir-x32.c b/gcc/ada/mkdir-x32.c
new file mode 100644
index 00000000000..0b625a3457d
--- /dev/null
+++ b/gcc/ada/mkdir-x32.c
@@ -0,0 +1,54 @@
+/****************************************************************************
+ * *
+ * GNAT COMPILER COMPONENTS *
+ * *
+ * M K D I R *
+ * *
+ * C Implementation File *
+ * *
+ * Copyright (C) 2015, Free Software Foundation, Inc. *
+ * *
+ * 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 3, 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. *
+ * *
+ * As a special exception under Section 7 of GPL version 3, you are granted *
+ * additional permissions described in the GCC Runtime Library Exception, *
+ * version 3.1, as published by the Free Software Foundation. *
+ * *
+ * You should have received a copy of the GNU General Public License and *
+ * a copy of the GCC Runtime Library Exception along with this program; *
+ * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see *
+ * <http://www.gnu.org/licenses/>. *
+ * *
+ * GNAT was originally developed by the GNAT team at New York University. *
+ * Extensive contributions were provided by Ada Core Technologies Inc. *
+ * *
+ ****************************************************************************/
+
+#if !defined (__linux__)
+#error Unsupported platform.
+#endif
+
+#ifdef IN_RTS
+#include "tconfig.h"
+#include "tsystem.h"
+#include <sys/stat.h>
+#else
+#include "config.h"
+#include "system.h"
+#endif
+
+#include "adaint.h"
+
+/* This function provides a portable binding to the mkdir function. */
+
+int
+__gnat_mkdir (uintptr_t dir_name_p, int encoding ATTRIBUTE_UNUSED)
+{
+ char *dir_name = (char *)dir_name_p;
+ return mkdir (dir_name, S_IRWXU | S_IRWXG | S_IRWXO);
+}
diff --git a/gcc/ada/s-crtl-x32.ads b/gcc/ada/s-crtl-x32.ads
new file mode 100644
index 00000000000..5f432ccf626
--- /dev/null
+++ b/gcc/ada/s-crtl-x32.ads
@@ -0,0 +1,241 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- S Y S T E M . C R T L --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2015, Free Software Foundation, Inc. --
+-- --
+-- 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 3, 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. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This package provides the low level interface to the C runtime library
+
+pragma Compiler_Unit_Warning;
+
+with System.Parameters;
+
+package System.CRTL is
+ pragma Preelaborate;
+
+ subtype chars is System.Address;
+ -- Pointer to null-terminated array of characters
+ -- Should use Interfaces.C.Strings types instead, but this causes bootstrap
+ -- issues as i-c contains Ada 2005 specific features, not compatible with
+ -- older, Ada 95-only base compilers???
+
+ subtype DIRs is System.Address;
+ -- Corresponds to the C type DIR*
+
+ subtype FILEs is System.Address;
+ -- Corresponds to the C type FILE*
+
+ subtype int is Integer;
+
+ type long is range -(2 ** (System.Parameters.long_bits - 1))
+ .. +(2 ** (System.Parameters.long_bits - 1)) - 1;
+
+ subtype off_t is Long_Integer;
+
+ type size_t is mod 2 ** Standard'Address_Size;
+
+ type ssize_t is range -(2 ** (Standard'Address_Size - 1))
+ .. +(2 ** (Standard'Address_Size - 1)) - 1;
+
+ type int64 is new Long_Long_Integer;
+ -- Note: we use Long_Long_Integer'First instead of -2 ** 63 to allow this
+ -- unit to compile when using custom target configuration files where the
+ -- maximum integer is 32 bits. This is useful for static analysis tools
+ -- such as SPARK or CodePeer. In the normal case, Long_Long_Integer is
+ -- always 64-bits so there is no difference.
+
+ type Filename_Encoding is (UTF8, ASCII_8bits, Unspecified);
+ for Filename_Encoding use (UTF8 => 0, ASCII_8bits => 1, Unspecified => 2);
+ pragma Convention (C, Filename_Encoding);
+ -- Describes the filename's encoding
+
+ --------------------
+ -- GCC intrinsics --
+ --------------------
+
+ -- The following functions are imported with convention Intrinsic so that
+ -- we take advantage of back-end builtins if present (else we fall back
+ -- to C library functions by the same names).
+
+ function strlen (A : System.Address) return size_t;
+ pragma Import (Intrinsic, strlen, "__gnat_strlen");
+
+ procedure strncpy (dest, src : System.Address; n : size_t);
+ pragma Import (Intrinsic, strncpy, "__gnat_strncpy");
+
+ -------------------------------
+ -- Other C runtime functions --
+ -------------------------------
+
+ function atoi (A : System.Address) return Integer;
+ pragma Import (C, atoi, "__gnat_atoi");
+
+ procedure clearerr (stream : FILEs);
+ pragma Import (C, clearerr, "__gnat_clearerr");
+
+ function dup (handle : int) return int;
+ pragma Import (C, dup, "dup");
+
+ function dup2 (from, to : int) return int;
+ pragma Import (C, dup2, "dup2");
+
+ function fclose (stream : FILEs) return int;
+ pragma Import (C, fclose, "__gnat_fclose");
+
+ function fdopen (handle : int; mode : chars) return FILEs;
+ pragma Import (C, fdopen, "__gnat_fdopen");
+
+ function fflush (stream : FILEs) return int;
+ pragma Import (C, fflush, "__gnat_fflush");
+
+ function fgetc (stream : FILEs) return int;
+ pragma Import (C, fgetc, "__gnat_fgetc");
+
+ function fgets (strng : chars; n : int; stream : FILEs) return chars;
+ pragma Import (C, fgets, "__gnat_fgets");
+
+ function fopen
+ (filename : chars;
+ mode : chars;
+ encoding : Filename_Encoding := Unspecified) return FILEs;
+ pragma Import (C, fopen, "__gnat_fopen");
+
+ function fputc (C : int; stream : FILEs) return int;
+ pragma Import (C, fputc, "__gnat_fputc");
+
+ function fputwc (C : int; stream : FILEs) return int;
+ pragma Import (C, fputwc, "__gnat_fputwc");
+
+ function fputs (Strng : chars; Stream : FILEs) return int;
+ pragma Import (C, fputs, "__gnat_fputs");
+
+ procedure free (Ptr : System.Address);
+ pragma Import (C, free, "__gnat_x32_free");
+
+ function freopen
+ (filename : chars;
+ mode : chars;
+ stream : FILEs;
+ encoding : Filename_Encoding := Unspecified) return FILEs;
+ pragma Import (C, freopen, "__gnat_freopen");
+
+ function fseek
+ (stream : FILEs;
+ offset : long;
+ origin : int) return int;
+ pragma Import (C, fseek, "__gnat_fseek");
+
+ function fseek64
+ (stream : FILEs;
+ offset : int64;
+ origin : int) return int;
+ pragma Import (C, fseek64, "__gnat_fseek64");
+
+ function ftell (stream : FILEs) return long;
+ pragma Import (C, ftell, "ftell");
+
+ function ftell64 (stream : FILEs) return int64;
+ pragma Import (C, ftell64, "__gnat_ftell64");
+
+ function getenv (S : String) return System.Address;
+ pragma Import (C, getenv, "__gnat_x32_getenv");
+
+ function isatty (handle : int) return int;
+ pragma Import (C, isatty, "isatty");
+
+ function lseek (fd : int; offset : off_t; direction : int) return off_t;
+ pragma Import (C, lseek, "lseek");
+
+ function malloc (Size : size_t) return System.Address;
+ pragma Import (C, malloc, "malloc");
+
+ procedure memcpy (S1 : System.Address; S2 : System.Address; N : size_t);
+ pragma Import (C, memcpy, "__gnat_memcpy");
+
+ procedure memmove (S1 : System.Address; S2 : System.Address; N : size_t);
+ pragma Import (C, memmove, "__gnat_memmove");
+
+ procedure mktemp (template : chars);
+ pragma Import (C, mktemp, "__gnat_mktemp");
+
+ function pclose (stream : System.Address) return int;
+ pragma Import (C, pclose, "__gnat_pclose");
+
+ function popen (command, mode : System.Address) return System.Address;
+ pragma Import (C, popen, "__gnat_popen");
+
+ function realloc
+ (Ptr : System.Address; Size : size_t) return System.Address;
+ pragma Import (C, realloc, "__gnat_x32_realloc");
+
+ procedure rewind (stream : FILEs);
+ pragma Import (C, rewind, "__gnat_rewind");
+
+ function rmdir (dir_name : String) return int;
+ pragma Import (C, rmdir, "__gnat_rmdir");
+
+ function chdir (dir_name : String) return int;
+ pragma Import (C, chdir, "__gnat_chdir");
+
+ function mkdir
+ (dir_name : String;
+ encoding : Filename_Encoding := Unspecified) return int;
+ pragma Import (C, mkdir, "__gnat_mkdir");
+
+ function setvbuf
+ (stream : FILEs;
+ buffer : chars;
+ mode : int;
+ size : size_t) return int;
+ pragma Import (C, setvbuf, "__gnat_setvbuf");
+
+ procedure tmpnam (str : chars);
+ pragma Import (C, tmpnam, "__gnat_tmpnam");
+
+ function tmpfile return FILEs;
+ pragma Import (C, tmpfile, "tmpfile");
+
+ function ungetc (c : int; stream : FILEs) return int;
+ pragma Import (C, ungetc, "__gnat_ungetc");
+
+ function unlink (filename : chars) return int;
+ pragma Import (C, unlink, "__gnat_unlink");
+
+ function open (filename : chars; oflag : int) return int;
+ pragma Import (C, open, "__gnat_open");
+
+ function close (fd : int) return int;
+ pragma Import (C, close, "close");
+
+ function read (fd : int; buffer : chars; count : size_t) return ssize_t;
+ pragma Import (C, read, "__gnat_read");
+
+ function write (fd : int; buffer : chars; count : size_t) return ssize_t;
+ pragma Import (C, write, "__gnat_write");
+
+end System.CRTL;