| /**************************************************************************** |
| * * |
| * GNAT COMPILER TOOLS * |
| * * |
| * G N A T B L * |
| * * |
| * C Implementation File * |
| * * |
| * Copyright (C) 1992-2003 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 2, or (at your option) any later ver- * |
| * sion. GNAT is distributed in the hope that it will be useful, but WITH- * |
| * OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * |
| * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * |
| * for more details. You should have received a copy of the GNU General * |
| * Public License distributed with GNAT; see file COPYING. If not, write * |
| * to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, * |
| * MA 02111-1307, USA. * |
| * * |
| * GNAT was originally developed by the GNAT team at New York University. * |
| * Extensive contributions were provided by Ada Core Technologies Inc. * |
| * * |
| ****************************************************************************/ |
| |
| #include "config.h" |
| #include "system.h" |
| |
| #if defined (__EMX__) || defined (MSDOS) |
| #include <process.h> |
| #endif |
| #include "adaint.h" |
| |
| #ifdef VMS |
| #ifdef exit |
| #undef exit |
| #endif |
| #define exit __posix_exit |
| #endif |
| |
| /* These can be set by command line arguments */ |
| char *binder_path = 0; |
| char *linker_path = 0; |
| char *exec_file_name = 0; |
| char *ali_file_name = 0; |
| #define BIND_ARG_MAX 512 |
| char *bind_args[BIND_ARG_MAX]; |
| int bind_arg_index = -1; |
| #ifdef MSDOS |
| char *coff2exe_path = 0; |
| char *coff2exe_args[] = {(char *) 0, (char *) 0}; |
| char *del_command = 0; |
| #endif |
| int verbose = 0; |
| int o_present = 0; |
| int g_present = 0; |
| |
| int link_arg_max = -1; |
| char **link_args = (char **) 0; |
| int link_arg_index = -1; |
| |
| char *gcc_B_arg = 0; |
| |
| #ifndef DIR_SEPARATOR |
| #if defined (__EMX__) |
| #define DIR_SEPARATOR '\\' |
| #else |
| #define DIR_SEPARATOR '/' |
| #endif |
| #endif |
| |
| static int linkonly = 0; |
| |
| static void addarg (char *); |
| static void process_args (int *, char *[]); |
| |
| static void |
| addarg (char *str) |
| { |
| int i; |
| |
| if (++link_arg_index >= link_arg_max) |
| { |
| char **new_link_args |
| = (char **) xcalloc (link_arg_max + 1000, sizeof (char *)); |
| |
| for (i = 0; i <= link_arg_max; i++) |
| new_link_args[i] = link_args[i]; |
| |
| if (link_args) |
| free (link_args); |
| |
| link_arg_max += 1000; |
| link_args = new_link_args; |
| } |
| |
| link_args[link_arg_index] = str; |
| } |
| |
| static void |
| process_args (int *p_argc, char *argv[]) |
| { |
| int i, j; |
| |
| for (i = 1; i < *p_argc; i++) |
| { |
| /* -I is passed on to gnatbind */ |
| if (! strncmp( argv[i], "-I", 2)) |
| { |
| bind_arg_index += 1; |
| if (bind_arg_index >= BIND_ARG_MAX) |
| { |
| fprintf (stderr, "Too many arguments to gnatbind\n"); |
| exit (-1); |
| } |
| |
| bind_args[bind_arg_index] = argv[i]; |
| } |
| |
| /* -B is passed on to gcc */ |
| if (! strncmp (argv[i], "-B", 2)) |
| gcc_B_arg = argv[i]; |
| |
| /* -v turns on verbose option here and is passed on to gcc */ |
| |
| if (! strcmp (argv[i], "-v")) |
| verbose = 1; |
| |
| if (! strcmp (argv[i], "-o")) |
| { |
| o_present = 1; |
| exec_file_name = argv[i + 1]; |
| } |
| |
| if (! strcmp (argv[i], "-g")) |
| g_present = 1; |
| |
| if (! strcmp (argv[i], "-gnatbind")) |
| { |
| /* Explicit naming of binder. Grab the value then remove the |
| two arguments from the argument list. */ |
| if ( i + 1 >= *p_argc ) |
| { |
| fprintf (stderr, "Missing argument for -gnatbind\n"); |
| exit (1); |
| } |
| |
| binder_path = __gnat_locate_exec (argv[i + 1], (char *) "."); |
| if (!binder_path) |
| { |
| fprintf (stderr, "Could not locate binder: %s\n", argv[i + 1]); |
| exit (1); |
| } |
| |
| for (j = i + 2; j < *p_argc; j++) |
| argv[j - 2] = argv[j]; |
| |
| (*p_argc) -= 2; |
| i--; |
| } |
| |
| else if (! strcmp (argv[i], "-linkonly")) |
| { |
| /* Don't call the binder. Set the flag and then remove the |
| argument from the argument list. */ |
| linkonly = 1; |
| for (j = i + 1; j < *p_argc; j++) |
| argv[j - 1] = argv[j]; |
| |
| *p_argc -= 1; |
| i--; |
| } |
| |
| else if (! strcmp (argv[i], "-gnatlink")) |
| { |
| /* Explicit naming of binder. Grab the value then remove the |
| two arguments from the argument list. */ |
| if (i + 1 >= *p_argc) |
| { |
| fprintf (stderr, "Missing argument for -gnatlink\n"); |
| exit (1); |
| } |
| |
| linker_path = __gnat_locate_exec (argv[i + 1], (char *) "."); |
| if (!linker_path) |
| { |
| fprintf (stderr, "Could not locate linker: %s\n", argv[i + 1]); |
| exit (1); |
| } |
| |
| for (j = i + 2; j < *p_argc; j++) |
| argv[j - 2] = argv[j]; |
| *p_argc -= 2; |
| i--; |
| } |
| } |
| } |
| extern int main (int, char **); |
| |
| int |
| main (int argc, char **argv) |
| { |
| int i, j; |
| int done_an_ali = 0; |
| int retcode; |
| #ifdef VMS |
| /* Warning: getenv only retrieves the first directory in VAXC$PATH */ |
| char *pathval = |
| xstrdup (__gnat_to_canonical_dir_spec (getenv ("VAXC$PATH"), 0)); |
| #else |
| char *pathval = getenv ("PATH"); |
| #endif |
| char *spawn_args[5]; |
| int spawn_index = 0; |
| |
| #if defined (__EMX__) || defined(MSDOS) |
| char *tmppathval = malloc (strlen (pathval) + 3); |
| strcpy (tmppathval, ".;"); |
| pathval = strcat (tmppathval, pathval); |
| #endif |
| |
| process_args (&argc , argv); |
| |
| if (argc == 1) |
| { |
| fprintf |
| (stdout, |
| "Usage: %s 'name'.ali\n", argv[0]); |
| fprintf |
| (stdout, |
| " [-o exec_name] -- by default it is 'name'\n"); |
| fprintf |
| (stdout, |
| " [-v] -- verbose mode\n"); |
| fprintf |
| (stdout, |
| " [-linkonly] -- doesn't call binder\n"); |
| fprintf |
| (stdout, |
| " [-gnatbind name] -- full name for gnatbind\n"); |
| fprintf |
| (stdout, |
| " [-gnatlink name] -- full name for linker (gcc)\n"); |
| fprintf |
| (stdout, |
| " [list of objects] -- non Ada binaries\n"); |
| fprintf |
| (stdout, |
| " [linker options] -- other options for linker\n"); |
| exit (1); |
| } |
| |
| if (!binder_path && !linkonly) |
| binder_path = __gnat_locate_exec ((char *) "gnatbind", pathval); |
| |
| if (!binder_path && !linkonly) |
| { |
| fprintf (stderr, "Couldn't locate gnatbind\n"); |
| exit (1); |
| } |
| |
| if (!linker_path) |
| linker_path = __gnat_locate_exec ((char *) "gnatlink", pathval); |
| if (!linker_path) |
| { |
| fprintf (stderr, "Couldn't locate gnatlink\n"); |
| exit (1); |
| } |
| |
| #ifdef MSDOS |
| coff2exe_path = __gnat_locate_regular_file ("coff2exe.bat", pathval); |
| if (!coff2exe_path) |
| { |
| fprintf (stderr, "Couldn't locate %s\n", "coff2exe.bat"); |
| exit (1); |
| } |
| else |
| coff2exe_args[0] = coff2exe_path; |
| #endif |
| |
| addarg (linker_path); |
| |
| for (i = 1; i < argc; i++) |
| { |
| int arg_len = strlen (argv[i]); |
| |
| if (arg_len > 4 && ! strcmp (&argv[i][arg_len - 4], ".ali")) |
| { |
| if (done_an_ali) |
| { |
| fprintf (stderr, |
| "Sorry - cannot handle more than one ALI file\n"); |
| exit (1); |
| } |
| |
| done_an_ali = 1; |
| |
| if (__gnat_is_regular_file (argv[i])) |
| { |
| ali_file_name = argv[i]; |
| if (!linkonly) |
| { |
| /* Run gnatbind */ |
| spawn_index = 0; |
| spawn_args[spawn_index++] = binder_path; |
| spawn_args[spawn_index++] = ali_file_name; |
| for (j = 0 ; j <= bind_arg_index ; j++ ) |
| spawn_args[spawn_index++] = bind_args[j]; |
| spawn_args[spawn_index] = 0; |
| |
| if (verbose) |
| { |
| int i; |
| for (i = 0; i < 2; i++) |
| printf ("%s ", spawn_args[i]); |
| |
| putchar ('\n'); |
| } |
| |
| retcode = __gnat_portable_spawn (spawn_args); |
| if (retcode != 0) |
| exit (retcode); |
| } |
| } |
| else |
| addarg (argv[i]); |
| } |
| #ifdef MSDOS |
| else if (!strcmp (argv[i], "-o")) |
| { |
| addarg (argv[i]); |
| if (i < argc) |
| i++; |
| |
| { |
| char *ptr = strstr (argv[i], ".exe"); |
| |
| arg_len = strlen (argv[i]); |
| coff2exe_args[1] = malloc (arg_len + 1); |
| strcpy (coff2exe_args[1], argv[i]); |
| if (ptr != NULL && strlen (ptr) == 4) |
| coff2exe_args[1][arg_len-4] = 0; |
| |
| addarg (coff2exe_args[1]); |
| } |
| } |
| #endif |
| else |
| addarg (argv[i]); |
| } |
| |
| if (! done_an_ali) |
| { |
| fprintf (stderr, "No \".ali\" file specified\n"); |
| exit (1); |
| } |
| |
| addarg (ali_file_name); |
| addarg (NULL); |
| |
| if (verbose) |
| { |
| int i; |
| |
| for (i = 0; i < link_arg_index; i++) |
| printf ("%s ", link_args[i]); |
| |
| putchar ('\n'); |
| } |
| |
| retcode = __gnat_portable_spawn (link_args); |
| if (retcode != 0) |
| exit (retcode); |
| |
| #ifdef MSDOS |
| retcode = __gnat_portable_spawn (coff2exe_args); |
| if (retcode != 0) |
| exit (retcode); |
| |
| if (!g_present) |
| { |
| del_command = malloc (strlen (coff2exe_args[1]) + 5); |
| sprintf (del_command, "del %s", coff2exe_args[1]); |
| retcode = system (del_command); |
| } |
| #endif |
| |
| exit(0); |
| } |