vms-ld.c, vms-cc.c: New files.
authorDouglas B Rupp <rupp@gnat.com>
Sun, 25 Nov 2001 11:30:17 +0000 (06:30 -0500)
committerRichard Kenner <kenner@gcc.gnu.org>
Sun, 25 Nov 2001 11:30:17 +0000 (06:30 -0500)
* config/alpha/vms-ld.c, config/alpha/vms-cc.c: New files.
* config/alpha/x-vms: New file, to compile the above.
* config.gcc (alpha*-dec-vms*): Add x-vms.

From-SVN: r47312

gcc/ChangeLog
gcc/config.gcc
gcc/config/alpha/vms-cc.c [new file with mode: 0644]
gcc/config/alpha/vms-ld.c [new file with mode: 0644]
gcc/config/alpha/x-vms [new file with mode: 0644]

index 1043d2d84d124a81627ce235d14654a23d999586..a324088cdcc133a2cdd2e843ebe55efbd4accc85 100644 (file)
@@ -1,3 +1,9 @@
+Sun Nov 25 06:22:09 2001  Douglas B. Rupp  <rupp@gnat.com>
+
+       * config/alpha/vms-ld.c, config/alpha/vms-cc.c: New files.
+       * config/alpha/x-vms: New file, to compile the above.
+       * config.gcc (alpha*-dec-vms*): Add x-vms.
+
 2001-11-24  Hans-Peter Nilsson  <hp@axis.com>
 
        * genextract.c (main): Set ro_loc for peepholes.
index b199dc47371aee968238ce842d7e6e471371bb52..bf262a6c2014a8106c1af2d0e76aad549cf041fb 100644 (file)
@@ -524,6 +524,7 @@ alpha*-dec-vms*)
        tm_file=alpha/vms.h
        xm_file=alpha/xm-vms.h
        tmake_file="alpha/t-alpha alpha/t-vms alpha/t-ieee"
+       xmake_file=alpha/x-vms
        ;;
 arc-*-elf*)
        tm_file="elfos.h svr4.h ${tm_file}"
diff --git a/gcc/config/alpha/vms-cc.c b/gcc/config/alpha/vms-cc.c
new file mode 100644 (file)
index 0000000..a95a82e
--- /dev/null
@@ -0,0 +1,379 @@
+/* VMS DEC C wrapper.
+   Copyright (C) 2001 Free Software Foundation, Inc.
+   Contributed by Douglas B. Rupp (rupp@gnat.com).
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT 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
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* This program is a wrapper around the VMS DEC C compiler.
+   It translates Unix style command line options into corresponding
+   VMS style qualifiers and then spawns the DEC C compiler.  */
+
+#include "config.h"
+#include "system.h"
+
+#undef PATH_SEPARATOR
+#undef PATH_SEPARATOR_STR
+#define PATH_SEPARATOR ','
+#define PATH_SEPARATOR_STR ","
+
+/* These can be set by command line arguments */
+int verbose = 0;
+int save_temps = 0;
+
+int comp_arg_max = -1;
+const char **comp_args = 0;
+int comp_arg_index = -1;
+char *objfilename = 0;
+
+char *system_search_dirs = (char *) "";
+char *search_dirs;
+
+char *default_defines = (char *) "";
+char *defines;
+
+/* Translate a Unix syntax directory specification into VMS syntax.
+   If indicators of VMS syntax found, return input string. */
+static char *to_host_dir_spec PARAMS ((char *));
+
+/* Translate a Unix syntax file specification into VMS syntax.
+   If indicators of VMS syntax found, return input string. */
+static char *to_host_file_spec PARAMS ((char *));
+
+/* Add a translated arg to the list to be passed to DEC CC */
+static void addarg PARAMS ((const char *));
+
+/* Preprocess the number of args in P_ARGC and contained in ARGV.
+   Look for special flags, etc. that must be handled first. */
+static void preprocess_args PARAMS ((*, **));
+
+/* Process the number of args in P_ARGC and contained in ARGV. Look
+   for special flags, etc. that must be handled for the VMS compiler. */
+static void process_args PARAMS ((int *, char **));
+
+/* Action routine called by decc$to_vms */
+static int translate_unix PARAMS ((char *, int));
+
+int main PARAMS ((int, char **));
+\f
+/* Add the argument contained in STR to the list of arguments to pass to the
+   compiler.  */
+
+static void
+addarg (str)
+     const char *str;
+{
+  int i;
+
+  if (++comp_arg_index >= comp_arg_max)
+    {
+      const char **new_comp_args
+       = (const char **) xcalloc (comp_arg_max + 1000, sizeof (char *));
+
+      for (i = 0; i <= comp_arg_max; i++)
+       new_comp_args [i] = comp_args [i];
+
+      if (comp_args)
+       free (comp_args);
+
+      comp_arg_max += 1000;
+      comp_args = new_comp_args;
+    }
+
+  comp_args [comp_arg_index] = str;
+}
+
+static void
+preprocess_args (p_argc, argv)
+     int *p_argc;
+     char *argv[];
+{
+  int i;
+
+  for (i = 1; i < *p_argc; i++)
+    {
+      if (strcmp (argv[i], "-o") == 0)
+       {
+         char *buff, *ptr;
+         int out_len;
+
+         i++;
+         ptr = to_host_file_spec (argv[i]);
+         objfilename = xstrdup (ptr);
+         out_len = strlen (ptr);
+         buff = xmalloc (out_len + 6);
+
+         strcpy (buff, "/obj=");
+         strcat (buff, ptr);
+         addarg (buff);
+       }
+    }
+}
+
+static void
+process_args (p_argc, argv)
+     int *p_argc;
+     char *argv[];
+{
+  int i;
+
+  for (i = 1; i < *p_argc; i++)
+    {
+      if (strlen (argv[i]) < 2)
+       continue;
+
+      if (strncmp (argv[i], "-I", 2) == 0)
+       {
+         char *ptr;
+         int new_len, search_dirs_len;
+
+         ptr = to_host_dir_spec (&argv[i][2]);
+         new_len = strlen (ptr);
+         search_dirs_len = strlen (search_dirs);
+
+         search_dirs = xrealloc (search_dirs, search_dirs_len + new_len + 2);
+         if (search_dirs_len > 0)
+           strcat (search_dirs, PATH_SEPARATOR_STR);
+         strcat (search_dirs, ptr);
+       }
+      else if (strncmp (argv[i], "-D", 2) == 0)
+       {
+         char *ptr;
+         int new_len, defines_len;
+
+         ptr = &argv[i][2];
+         new_len = strlen (ptr);
+         defines_len = strlen (defines);
+
+         defines = xrealloc (defines, defines_len + new_len + 4);
+         if (defines_len > 0)
+           strcat (defines, ",");
+
+         strcat (defines, "\"");
+         strcat (defines, ptr);
+         strcat (defines, "\"");
+       }
+      else if (strcmp (argv[i], "-v") == 0)
+       verbose = 1;
+      else if (strcmp (argv[i], "-g0") == 0)
+       addarg ("/nodebug");
+      else if (strcmp (argv[i], "-O0") == 0)
+       addarg ("/noopt");
+      else if (strncmp (argv[i], "-g", 2) == 0)
+       addarg ("/debug");
+      else if (strcmp (argv[i], "-E") == 0)
+       addarg ("/preprocess");
+      else if (strcmp (argv[i], "-save-temps") == 0)
+       save_temps = 1;
+    }
+}
+
+/* The main program.  Spawn the VMS DEC C compiler after fixing up the
+   Unix-like flags and args to be what VMS DEC C wants.  */
+
+typedef struct dsc {unsigned short len, mbz; char *adr; } Descr;
+
+int
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  int i;
+  char cwdev [128], *devptr;
+  int devlen;
+  char *cwd = getcwd (0, 1024);
+
+  devptr = strchr (cwd, ':');
+  devlen = (devptr - cwd) + 1;
+  strncpy (cwdev, cwd, devlen);
+  cwdev [devlen] = '\0';
+
+  search_dirs = xmalloc (strlen (system_search_dirs) + 1);
+  strcpy (search_dirs, system_search_dirs);
+
+  defines = xmalloc (strlen (default_defines) + 1);
+  strcpy (defines, default_defines);
+
+  addarg ("cc");
+  preprocess_args (&argc , argv);
+  process_args (&argc , argv);
+
+  if (strlen (search_dirs) > 0)
+    {
+      addarg ("/include=(");
+      addarg (search_dirs);
+      addarg (")");
+    }
+
+  if (strlen (defines) > 0)
+    {
+      addarg ("/define=(");
+      addarg (defines);
+      addarg (")");
+    }
+
+  for (i = 1; i < argc; i++)
+    {
+      int arg_len = strlen (argv[i]);
+
+      if (strcmp (argv[i], "-o") == 0)
+       i++;
+      else if (strcmp (argv[i], "-v" ) == 0
+              || strcmp (argv[i], "-E") == 0
+              || strcmp (argv[i], "-c") == 0
+              || strncmp (argv[i], "-g", 2 ) == 0
+              || strncmp (argv[i], "-O", 2 ) == 0
+              || strcmp (argv[i], "-save-temps") == 0
+              || (arg_len > 2 && strncmp (argv[i], "-I", 2) == 0)
+              || (arg_len > 2 && strncmp (argv[i], "-D", 2) == 0))
+       ;
+
+      /* Unix style file specs and VMS style switches look alike, so assume
+        an arg consisting of one and only one slash, and that being first, is
+        really a switch.  */
+      else if ((argv[i][0] == '/') && (strchr (&argv[i][1], '/') == 0))
+       addarg (argv[i]);
+      else
+       {
+         /* Assume filename arg */
+         char buff [256], *ptr;
+         int buff_len;
+
+         ptr = to_host_file_spec (argv[i]);
+         arg_len = strlen (ptr);
+
+         if (ptr[0] == '[')
+           sprintf (buff, "%s%s", cwdev, ptr);
+         else if (strchr (ptr, ':'))
+           sprintf (buff, "%s", ptr);
+         else
+           sprintf (buff, "%s%s", cwd, ptr);
+
+         buff_len = strlen (buff);
+         ptr = xmalloc (buff_len + 1);
+
+         strcpy (ptr, buff);
+         addarg (ptr);
+       }
+    }
+
+  addarg (NULL);
+
+  if (verbose)
+    {
+      int i;
+
+      for (i = 0; i < comp_arg_index; i++)
+       printf ("%s ", comp_args [i]);
+
+      putchar ('\n');
+    }
+
+  {
+    int i;
+    int len = 0;
+
+    for (i = 0; comp_args[i]; i++)
+      len = len + strlen (comp_args[i]) + 1;
+
+    {
+      char *allargs = (char *) alloca (len + 1);
+      Descr cmd;
+      int status;
+      int status1 = 1;
+
+      for (i = 0; i < len + 1; i++)
+       allargs [i] = 0;
+
+      for (i = 0; comp_args [i]; i++)
+       {
+         strcat (allargs, comp_args [i]);
+         strcat (allargs, " ");
+       }
+
+      cmd.adr = allargs;
+      cmd.len = len;
+      cmd.mbz = 0;
+
+      i = LIB$SPAWN (&cmd, 0, 0, 0, 0, 0, &status);
+
+      if ((i & 1) != 1)
+       {
+         LIB$SIGNAL (i);
+         exit (1);
+       }
+
+      if ((status & 1) == 1 && (status1 & 1) == 1)
+       exit (0);
+
+      exit (1);
+    }
+  }
+}
+
+static char new_host_filespec [255];
+static char new_host_dirspec [255];
+static char filename_buff [256];
+
+static int
+translate_unix (name, type)
+     char *name;
+     int type ATTRIBUTE_UNUSED;
+{
+  strcpy (filename_buff, name);
+  return 0;
+}
+
+static char *
+to_host_dir_spec (dirspec)
+     char *dirspec;
+{
+  int len = strlen (dirspec);
+
+  strcpy (new_host_dirspec, dirspec);
+
+  if (strchr (new_host_dirspec, ']') || strchr (new_host_dirspec, ':'))
+    return new_host_dirspec;
+
+  while (len > 1 && new_host_dirspec [len-1] == '/')
+    {
+      new_host_dirspec [len-1] = 0;
+      len--;
+    }
+
+  decc$to_vms (new_host_dirspec, translate_unix, 1, 2);
+  strcpy (new_host_dirspec, filename_buff);
+
+  return new_host_dirspec;
+
+}
+
+static char *
+to_host_file_spec (filespec)
+     char *filespec;
+{
+  strcpy (new_host_filespec, "");
+  if (strchr (filespec, ']') || strchr (filespec, ':'))
+    strcpy (new_host_filespec, filespec);
+  else
+    {
+      decc$to_vms (filespec, translate_unix, 1, 1);
+      strcpy (new_host_filespec, filename_buff);
+    }
+
+  return new_host_filespec;
+}
diff --git a/gcc/config/alpha/vms-ld.c b/gcc/config/alpha/vms-ld.c
new file mode 100644 (file)
index 0000000..f28b7c7
--- /dev/null
@@ -0,0 +1,762 @@
+/* VMS linker wrapper.
+   Copyright (C) 1996-2001 Free Software Foundation, Inc.
+   Contributed by Douglas B. Rupp (rupp@gnat.com).
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT 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
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* This program is a wrapper around the VMS linker.
+   It translates Unix style command line options into corresponding
+   VMS style qualifiers and then spawns the VMS linker.  */
+
+#include "config.h"
+#include "system.h"
+
+typedef struct dsc {unsigned short len, mbz; char *adr; } Descr;
+
+#undef PATH_SEPARATOR
+#undef PATH_SEPARATOR_STR
+#define PATH_SEPARATOR ','
+#define PATH_SEPARATOR_STR ","
+
+/* Local variable declarations.  */
+
+/* File specification for vms-dwarf2.o.  */
+static char *vmsdwarf2spec = 0;
+
+/* verbose = 1 if -v passed.   */
+static int verbose = 0;
+
+/* save_temps = 1 if -save-temps passed.  */
+static int save_temps = 0;
+
+/* By default don't generate executable file if there are errors
+   in the link. Override with --noinhibit-exec.  */
+static int inhibit_exec = 1;
+
+/* debug = 1 if -g passed.  */
+static int debug = 0;
+
+/* By default prefer to link with shareable image libraries.
+   Override with -static.  */
+static int staticp = 0;
+
+/* By default generate an executable, not a shareable image library.
+   Override with -shared.  */
+static int share = 0;
+
+/* Remember if IDENTIFICATION given on command line.  */
+static int ident = 0;
+
+/* Keep track of arg translations.  */
+static int link_arg_max = -1;
+static const char **link_args = 0;
+static int link_arg_index = -1;
+
+/* Keep track of filenames */
+static char optfilefullname [267];
+static char *sharefilename = 0;
+static char *exefilename = 0;
+
+/* System search dir list. Leave blank since link handles this
+   internally.  */
+static char *system_search_dirs = "";
+
+/* Search dir list passed on command line (with -L).  */
+static char *search_dirs;
+
+/* Local function declarations.  */
+
+/* Add STR to the list of arguments to pass to the linker. Expand the list as
+   necessary to accomodate.  */
+static void addarg PARAMS ((const char *));
+
+/* Check to see if NAME is a regular file, i.e. not a directory */
+static int is_regular_file PARAMS ((char *));
+
+/* Translate a Unix syntax file specification FILESPEC into VMS syntax.
+   If indicators of VMS syntax found, return input string. */
+static char *to_host_file_spec PARAMS ((char *));
+
+/* Locate the library named LIB_NAME in the set of paths PATH_VAL. */
+static char *locate_lib PARAMS ((char *, char *));
+
+/* Given a library name NAME, i.e. foo,  Look for libfoo.lib and then
+   libfoo.a in the set of directories we are allowed to search in.  */
+static const char *expand_lib PARAMS ((char *));
+
+/* Preprocess the number of args P_ARGC in ARGV.
+   Look for special flags, etc. that must be handled first. */
+static void preprocess_args PARAMS ((int *, char **));
+
+/* Preprocess the number of args P_ARGC in ARGV.  Look for
+   special flags, etc. that must be handled for the VMS linker. */
+static void process_args PARAMS ((int *, char **));
+
+/* Action routine called by decc$to_vms. NAME is a file name or
+   directory name. TYPE is unused. */
+static int translate_unix PARAMS ((char *, int));
+
+int main PARAMS ((int, char **));
+\f
+static void
+addarg (str)
+     const char *str;
+{
+  int i;
+
+  if (++link_arg_index >= link_arg_max)
+    {
+      const char **new_link_args
+       = (const 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 char *
+locate_lib (lib_name, path_val)
+     char *lib_name;
+     char *path_val;
+{
+  int lib_len = strlen (lib_name);
+  char *eptr, *sptr;
+
+  for (sptr = path_val; *sptr; sptr = eptr)
+    {
+      char *buf, *ptr;
+
+      while (*sptr == PATH_SEPARATOR)
+       sptr ++;
+
+      eptr = strchr (sptr, PATH_SEPARATOR);
+      if (eptr == 0)
+       eptr = strchr (sptr, 0);
+
+      buf = alloca ((eptr-sptr) + lib_len + 4 + 2);
+      strncpy (buf, sptr, eptr-sptr);
+      buf [eptr-sptr] = 0;
+      strcat (buf, "/");
+      strcat (buf, lib_name);
+      ptr = strchr (buf, 0);
+
+      if (debug || staticp)
+       {
+         /* For debug or static links, look for shareable image libraries
+            last.  */
+         strcpy (ptr, ".a");
+         if (is_regular_file (buf))
+           return xstrdup (to_host_file_spec (buf));
+
+         strcpy (ptr, ".olb");
+         if (is_regular_file (buf))
+           return xstrdup (to_host_file_spec (buf));
+
+         strcpy (ptr, ".exe");
+         if (is_regular_file (buf))
+           return xstrdup (to_host_file_spec (buf));
+       }
+      else
+       {
+         /* Otherwise look for shareable image libraries first.  */
+         strcpy (ptr, ".exe");
+         if (is_regular_file (buf))
+           return xstrdup (to_host_file_spec (buf));
+
+         strcpy (ptr, ".a");
+         if (is_regular_file (buf))
+           return xstrdup (to_host_file_spec (buf));
+
+         strcpy (ptr, ".olb");
+         if (is_regular_file (buf))
+           return xstrdup (to_host_file_spec (buf));
+       }
+    }
+
+  return 0;
+}
+
+static const char *
+expand_lib (name)
+     char *name;
+{
+  char *lib, *lib_path;
+
+  if (strcmp (name, "c") == 0)
+    /* IEEE VAX C compatible library for non-prefixed (e.g. no DECC$)
+       C RTL functions.  */
+    return "sys$library:vaxcrtltx.olb";
+
+  else if (strcmp (name, "m") == 0)
+    /* No separate library for math functions */
+    return "";
+
+  else
+    {
+      lib = xmalloc (strlen (name) + 14);
+
+      strcpy (lib, "lib");
+      strcat (lib, name);
+      lib_path = locate_lib (lib, search_dirs);
+
+      if (lib_path)
+       return lib_path;
+    }
+
+  fprintf (stderr,
+          "Couldn't locate library: lib%s.exe, lib%s.a or lib%s.olb\n",
+          name, name, name);
+
+  exit (1);
+}
+
+static int
+is_regular_file (name)
+     char *name;
+{
+  int ret;
+  struct stat statbuf;
+
+  ret = stat (name, &statbuf);
+  return !ret && S_ISREG (statbuf.st_mode);
+}
+
+static void
+preprocess_args (p_argc, argv)
+     int *p_argc;
+     char **argv;
+{
+  int i;
+
+  for (i = 1; i < *p_argc; i++)
+    if (strlen (argv[i]) >= 6 && strncmp (argv[i], "-shared", 7) == 0)
+      share = 1;
+
+  for (i = 1; i < *p_argc; i++)
+    if (strcmp (argv[i], "-o") == 0)
+      {
+       char *buff, *ptr;
+       int out_len;
+       int len;
+
+       i++;
+       ptr = to_host_file_spec (argv[i]);
+       exefilename = xstrdup (ptr);
+       out_len = strlen (ptr);
+       buff = xmalloc (out_len + 18);
+
+       if (share)
+         strcpy (buff, "/share=");
+       else
+         strcpy (buff, "/exe=");
+
+       strcat (buff, ptr);
+       addarg (buff);
+
+       if (share)
+         {
+           sharefilename = xmalloc (out_len+5);
+           if (ptr == strchr (argv[i], ']'))
+             strcpy (sharefilename, ++ptr);
+           else if (ptr == strchr (argv[i], ':'))
+             strcpy (sharefilename, ++ptr);
+           else if (ptr == strrchr (argv[i], '/'))
+             strcpy (sharefilename, ++ptr);
+           else
+             strcpy (sharefilename, argv[i]);
+
+           len = strlen (sharefilename);
+           if (strncasecmp (&sharefilename[len-4], ".exe", 4) == 0)
+             sharefilename[len-4] = 0;
+
+           for (ptr = sharefilename; *ptr; ptr++)
+             *ptr = TOUPPER (*ptr);
+         }
+      }
+}
+
+static void
+process_args (p_argc, argv)
+     int *p_argc;
+     char **argv;
+{
+  int i;
+
+  for (i = 1; i < *p_argc; i++)
+    {
+      if (strlen (argv[i]) < 2)
+       continue;
+
+      if (strncmp (argv[i], "-L", 2) == 0)
+       {
+         char *nbuff, *ptr;
+         int new_len, search_dirs_len;
+
+         ptr = &argv[i][2];
+         new_len = strlen (ptr);
+         search_dirs_len = strlen (search_dirs);
+
+         nbuff = xmalloc (new_len + 1);
+         strcpy (nbuff, ptr);
+
+         /* Remove trailing slashes.  */
+         while (new_len > 1 && nbuff [new_len - 1] == '/')
+           {
+             nbuff [new_len - 1] = 0;
+             new_len--;
+           }
+
+         search_dirs = xrealloc (search_dirs, search_dirs_len + new_len + 2);
+         if (search_dirs_len > 0)
+           strcat (search_dirs, PATH_SEPARATOR_STR);
+
+         strcat (search_dirs, nbuff);
+         free (nbuff);
+       }
+
+      /* -v turns on verbose option here and is passed on to gcc.  */
+      else if (strcmp (argv[i], "-v") == 0)
+       verbose = 1;
+      else if (strcmp (argv[i], "-g0") == 0)
+       addarg ("/notraceback");
+      else if (strncmp (argv[i], "-g", 2) == 0)
+       {
+         addarg ("/debug");
+         debug = 1;
+       }
+      else if (strcmp (argv[i], "-static") == 0)
+       staticp = 1;
+      else if (strcmp (argv[i], "-map") == 0)
+       {
+         char *buff, *ptr;
+
+         buff = xmalloc (strlen (exefilename) + 5);
+         strcpy (buff, exefilename);
+         ptr = strchr (buff, '.');
+         if (ptr)
+           *ptr = 0;
+
+         strcat (buff, ".map");
+         addarg ("/map=");
+         addarg (buff);
+         addarg ("/full");
+       }
+      else if (strcmp (argv[i], "-save-temps") == 0)
+       save_temps = 1;
+      else if (strcmp (argv[i], "--noinhibit-exec") == 0)
+       inhibit_exec = 0;
+    }
+}
+
+/* The main program.  Spawn the VMS linker after fixing up the Unix-like flags
+   and args to be what the VMS linker wants.  */
+
+int
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  int i;
+  char cwdev [128], *devptr;
+  int devlen;
+  int optfd;
+  FILE *optfile;
+  char *cwd = getcwd (0, 1024);
+  char *optfilename;
+
+  devptr = strchr (cwd, ':');
+  devlen = (devptr - cwd) + 1;
+  strncpy (cwdev, cwd, devlen);
+  cwdev [devlen] = '\0';
+
+  search_dirs = xmalloc (strlen (system_search_dirs) + 1);
+  strcpy (search_dirs, system_search_dirs);
+
+  addarg ("link");
+
+  /* Pass to find args that have to be append first.  */
+  preprocess_args (&argc , argv);
+
+  /* Pass to find the rest of the args.  */
+  process_args (&argc , argv);
+
+  /* Create a temp file to hold args, otherwise we can easily exceed the VMS
+     command line length limits.  */
+  optfilename = alloca (strlen ("LDXXXXXX") + 1);
+  strcpy (optfilename, "LDXXXXXX");
+  optfd = mkstemp (optfilename);
+  getcwd (optfilefullname, 256, 1); /* VMS style cwd.  */
+  strcat (optfilefullname, optfilename);
+  strcat (optfilefullname, ".");
+  optfile = fdopen (optfd, "w");
+
+  /* Write out the IDENTIFICATION argument first so that it can be overridden
+     by an options file.  */
+  for (i = 1; i < argc; i++)
+    {
+      int arg_len = strlen (argv[i]);
+
+      if (arg_len > 6 && strncasecmp (argv[i], "IDENT=", 6) == 0)
+       {
+         /* Comes from command line. If present will always appear before
+            IDENTIFICATION=... and will override.  */
+
+         if (!ident)
+           ident = 1;
+       }
+      else if (arg_len > 15
+              && strncasecmp (argv[i], "IDENTIFICATION=", 15) == 0)
+       {
+         /* Comes from pragma Ident ().  */
+
+         if (!ident)
+           {
+             fprintf (optfile, "case_sensitive=yes\n");
+             fprintf (optfile, "IDENTIFICATION=\"%15.15s\"\n", &argv[i][15]);
+             fprintf (optfile, "case_sensitive=NO\n");
+             ident = 1;
+           }
+       }
+    }
+
+  for (i = 1; i < argc; i++)
+    {
+      int arg_len = strlen (argv[i]);
+
+      if (strcmp (argv[i], "-o") == 0)
+       i++;
+      else if (arg_len > 2 && strncmp (argv[i], "-l", 2) == 0)
+       {
+         const char *libname = expand_lib (&argv[i][2]);
+         const char *ext;
+         int len;
+
+         if ((len = strlen (libname)) > 0)
+           {
+             char buff [256];
+
+             if (len > 4 && strcasecmp (&libname [len-4], ".exe") == 0)
+               ext = "/shareable";
+             else
+               ext = "/library";
+
+             if (libname[0] == '[')
+               sprintf (buff, "%s%s", cwdev, libname);
+             else
+               sprintf (buff, "%s", libname);
+
+             fprintf (optfile, "%s%s\n", buff, ext);
+           }
+       }
+
+      else if (strcmp (argv[i], "-v" ) == 0
+              || strncmp (argv[i], "-g", 2 ) == 0
+              || strcmp (argv[i], "-static" ) == 0
+              || strcmp (argv[i], "-map" ) == 0
+              || strcmp (argv[i], "-save-temps") == 0
+              || strcmp (argv[i], "--noinhibit-exec") == 0
+              || (arg_len > 2 && strncmp (argv[i], "-L", 2) == 0)
+              || (arg_len >= 6 && strncmp (argv[i], "-share", 6) == 0))
+       ;
+      else if (arg_len > 1 && argv[i][0] == '@')
+       {
+         FILE *atfile;
+         char *ptr, *ptr1;
+         struct stat statbuf;
+         char *buff;
+         int len;
+
+         if (stat (&argv[i][1], &statbuf))
+           {
+             fprintf (stderr, "Couldn't open linker response file: %s\n",
+                      &argv[i][1]);
+             exit (1);
+           }
+
+         buff = xmalloc (statbuf.st_size + 1);
+         atfile = fopen (&argv[i][1], "r");
+         fgets (buff, statbuf.st_size + 1, atfile);
+         fclose (atfile);
+
+         len = strlen (buff);
+         if (buff [len - 1] == '\n')
+           {
+             buff [len - 1] = 0;
+             len--;
+           }
+
+         ptr = buff;
+
+         do
+         {
+            ptr1 = strchr (ptr, ' ');
+            if (ptr1)
+              *ptr1 = 0;
+            ptr = to_host_file_spec (ptr);
+            if (ptr[0] == '[')
+              fprintf (optfile, "%s%s\n", cwdev, ptr);
+            else
+              fprintf (optfile, "%s\n", ptr);
+            ptr = ptr1 + 1;
+         } while (ptr1);
+       }
+
+      /* Unix style file specs and VMS style switches look alike, so assume an
+        arg consisting of one and only one slash, and that being first, is
+        really a switch.  */
+      else if ((argv[i][0] == '/') && (strchr (&argv[i][1], '/') == 0))
+       addarg (argv[i]);
+      else if (arg_len > 4
+              && strncasecmp (&argv[i][arg_len-4], ".OPT", 4) == 0)
+       {
+         FILE *optfile1;
+         char buff [256];
+
+         optfile1 = fopen (argv[i], "r");
+         while (fgets (buff, 256, optfile1))
+           fputs (buff, optfile);
+
+         fclose (optfile1);
+       }
+      else if (arg_len > 7 && strncasecmp (argv[i], "GSMATCH", 7) == 0)
+       fprintf (optfile, "%s\n", argv[i]);
+      else if (arg_len > 6 && strncasecmp (argv[i], "IDENT=", 6) == 0)
+       {
+         /* Comes from command line and will override pragma.  */
+         fprintf (optfile, "case_sensitive=yes\n");
+         fprintf (optfile, "IDENT=\"%15.15s\"\n", &argv[i][6]);
+         fprintf (optfile, "case_sensitive=NO\n");
+         ident = 1;
+       }
+      else if (arg_len > 15
+              && strncasecmp (argv[i], "IDENTIFICATION=", 15) == 0)
+       ;
+      else
+       {
+         /* Assume filename arg.  */
+         const char *addswitch = "";
+         char buff [256];
+         int buff_len;
+         int is_cld = 0;
+
+         argv[i] = to_host_file_spec (argv[i]);
+         arg_len = strlen (argv[i]);
+
+         if (arg_len > 4 && strcasecmp (&argv[i][arg_len-4], ".exe") == 0)
+           addswitch = "/shareable";
+
+         if (arg_len > 4 && strcasecmp (&argv[i][arg_len-4], ".cld") == 0)
+           {
+             addswitch = "/shareable";
+             is_cld = 1;
+           }
+
+         if (arg_len > 2 && strcasecmp (&argv[i][arg_len-2], ".a") == 0)
+           addswitch = "/lib";
+
+         if (arg_len > 4 && strcasecmp (&argv[i][arg_len-4], ".olb") == 0)
+           addswitch = "/lib";
+
+         if (argv[i][0] == '[')
+           sprintf (buff, "%s%s%s\n", cwdev, argv[i], addswitch);
+         else if (strchr (argv[i], ':'))
+           sprintf (buff, "%s%s\n", argv[i], addswitch);
+         else
+           sprintf (buff, "%s%s%s\n", cwd, argv[i], addswitch);
+
+         buff_len = strlen (buff);
+
+         if (buff_len >= 13
+             && strcasecmp (&buff[buff_len-13],"vms-dwarf2.o\n") == 0)
+           vmsdwarf2spec = xstrdup (buff);
+         else if (is_cld)
+           {
+             addarg (buff);
+             addarg (",");
+           }
+         else
+           fprintf (optfile, buff);
+       }
+    }
+
+#if 0
+  if (share)
+    fprintf (optfile, "symbol_vector=(main=procedure)\n");
+#endif
+
+  if (debug && vmsdwarf2spec)
+    {
+      fprintf (optfile, "case_sensitive=yes\n");
+      fprintf (optfile, "cluster=DWARF2debug,,,%s", vmsdwarf2spec);
+      fprintf (optfile, "collect=DWARF2debug,debug_abbrev,debug_aranges,-\n");
+      fprintf (optfile, " debug_frame,debug_info,debug_line,debug_loc,-\n");
+      fprintf (optfile,
+              " debug_macinfo,debug_pubnames,debug_str,debug_zzzzzz\n");
+      fprintf (optfile, "case_sensitive=NO\n");
+    }
+
+  if (debug && share)
+    {
+      fprintf (optfile, "case_sensitive=yes\n");
+      fprintf (optfile, "symbol_vector=(-\n");
+      fprintf (optfile,
+              "%s$DWARF2.DEBUG_ABBREV/$dwarf2.debug_abbrev=DATA,-\n",
+              sharefilename);
+      fprintf (optfile,
+              "%s$DWARF2.DEBUG_ARANGES/$dwarf2.debug_aranges=DATA,-\n",
+              sharefilename);
+      fprintf (optfile, "%s$DWARF2.DEBUG_FRAME/$dwarf2.debug_frame=DATA,-\n",
+              sharefilename);
+      fprintf (optfile, "%s$DWARF2.DEBUG_INFO/$dwarf2.debug_info=DATA,-\n",
+              sharefilename);
+      fprintf (optfile, "%s$DWARF2.DEBUG_LINE/$dwarf2.debug_line=DATA,-\n",
+              sharefilename);
+      fprintf (optfile, "%s$DWARF2.DEBUG_LOC/$dwarf2.debug_loc=DATA,-\n",
+              sharefilename);
+      fprintf (optfile,
+              "%s$DWARF2.DEBUG_MACINFO/$dwarf2.debug_macinfo=DATA,-\n",
+              sharefilename);
+      fprintf (optfile,
+              "%s$DWARF2.DEBUG_PUBNAMES/$dwarf2.debug_pubnames=DATA,-\n",
+              sharefilename);
+      fprintf (optfile, "%s$DWARF2.DEBUG_STR/$dwarf2.debug_str=DATA,-\n",
+              sharefilename);
+      fprintf (optfile, "%s$DWARF2.DEBUG_ZZZZZZ/$dwarf2.debug_zzzzzz=DATA)\n",
+              sharefilename);
+      fprintf (optfile, "case_sensitive=NO\n");
+    }
+
+  fclose (optfile);
+  addarg (optfilefullname);
+  addarg ("/opt");
+
+  addarg (NULL);
+
+  if (verbose)
+    {
+      int i;
+
+      for (i = 0; i < link_arg_index; i++)
+       printf ("%s ", link_args [i]);
+      putchar ('\n');
+    }
+
+  {
+    int i;
+    int len = 0;
+
+    for (i = 0; link_args[i]; i++)
+      len = len + strlen (link_args[i]) + 1;
+
+    {
+      char *allargs = (char *) alloca (len + 1);
+      Descr cmd;
+      int status;
+      int status1 = 1;
+
+      for (i = 0; i < len + 1; i++)
+       allargs [i] = 0;
+
+      for (i = 0; link_args [i]; i++)
+       {
+         strcat (allargs, link_args [i]);
+         strcat (allargs, " ");
+       }
+
+      cmd.adr = allargs;
+      cmd.len = len;
+      cmd.mbz = 0;
+
+      i = LIB$SPAWN (&cmd, 0, 0, 0, 0, 0, &status);
+      if ((i & 1) != 1)
+       {
+         LIB$SIGNAL (i);
+         exit (1);
+       }
+
+      if (debug && !share)
+       {
+         strcpy (allargs, "@gnu:[bin]set_exe ");
+         strcat (allargs, exefilename);
+         strcat (allargs, " /nodebug /silent");
+         len = strlen (allargs);
+         cmd.adr = allargs;
+         cmd.len = len;
+         cmd.mbz = 0;
+
+         if (verbose)
+           printf (allargs);
+
+         i = LIB$SPAWN (&cmd, 0, 0, 0, 0, 0, &status1);
+
+         if ((i & 1) != 1)
+           {
+             LIB$SIGNAL (i);
+             exit (1);
+           }
+       }
+
+      if (!save_temps)
+       remove (optfilefullname);
+
+      if ((status & 1) == 1 && (status1 & 1) == 1)
+       exit (0);
+
+      if (exefilename && inhibit_exec == 1)
+       remove (exefilename);
+
+      exit (1);
+    }
+  }
+}
+
+static char new_host_filespec [255];
+static char filename_buff [256];
+
+static int
+translate_unix (name, type)
+     char *name;
+     int type ATTRIBUTE_UNUSED;
+{
+  strcpy (filename_buff, name);
+  return 0;
+}
+
+static char *
+to_host_file_spec (filespec)
+     char *filespec;
+{
+  strcpy (new_host_filespec, "");
+  if (strchr (filespec, ']') || strchr (filespec, ':'))
+    strcpy (new_host_filespec, filespec);
+  else
+    {
+      decc$to_vms (filespec, translate_unix, 1, 1);
+      strcpy (new_host_filespec, filename_buff);
+    }
+
+  return new_host_filespec;
+}
diff --git a/gcc/config/alpha/x-vms b/gcc/config/alpha/x-vms
new file mode 100644 (file)
index 0000000..49338c1
--- /dev/null
@@ -0,0 +1,11 @@
+vms-ld.o : $(srcdir)/config/alpha/vms-ld.c
+       $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
+ld.exe : vms-ld.o
+       $(CC) -o $@ vms-ld.o ../libiberty/libiberty.a
+
+vms-cc.o : $(srcdir)/config/alpha/vms-cc.c
+       $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
+decc.exe : vms-cc.o
+       $(CC) -o $@ vms-cc.o ../libiberty/libiberty.a
+
+EXTRA_PROGRAMS=ld.exe decc.exe