diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2015-04-01 16:43:50 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2015-04-17 07:39:54 -0700 |
commit | 463448deaf3d937bdc3b32634c8a164742e23b1d (patch) | |
tree | 1458b803f1ba1fd79a1f0d48f5c41602c75a6b5d | |
parent | a94214bb1dea4a24ccb457da3522f1952fd5ae35 (diff) | |
download | gcc-463448deaf3d937bdc3b32634c8a164742e23b1d.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.c | 2004 | ||||
-rw-r--r-- | gcc/ada/adaint-x32.h | 313 | ||||
-rw-r--r-- | gcc/ada/argv-x32.c | 123 | ||||
-rw-r--r-- | gcc/ada/cstreams-x32.c | 224 | ||||
-rw-r--r-- | gcc/ada/gcc-interface/Makefile.in | 7 | ||||
-rw-r--r-- | gcc/ada/init-x32.c | 651 | ||||
-rw-r--r-- | gcc/ada/mkdir-x32.c | 54 | ||||
-rw-r--r-- | gcc/ada/s-crtl-x32.ads | 241 |
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; |