OSDN Git Service

more rigorous SIGCHLD guarding
[pf3gnuchains/gcc-fork.git] / gcc / collect2.c
index 456716c..729d62d 100644 (file)
@@ -1,6 +1,7 @@
 /* Collect static initialization info into data structures that can be
    traversed by C++ initialization and finalization routines.
-   Copyright (C) 1992, 93-97, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+   1999, 2000, 2001 Free Software Foundation, Inc.
    Contributed by Chris Smith (csmith@convex.com).
    Heavily modified by Michael Meissner (meissner@cygnus.com),
    Per Bothner (bothner@cygnus.com), and John Gilmore (gnu@cygnus.com).
@@ -26,75 +27,40 @@ Boston, MA 02111-1307, USA.  */
 /* Build tables of static constructors and destructors and run ld.  */
 
 #include "config.h"
-#include <sys/types.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <errno.h>
+#include "system.h"
 #include <signal.h>
-#include <sys/file.h>
-#include <sys/stat.h>
-
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
+#if ! defined( SIGCHLD ) && defined( SIGCLD )
+#  define SIGCHLD SIGCLD
 #endif
 
-#ifdef HAVE_STRING_H
-#include <string.h>
+#ifdef vfork /* Autoconf may define this to fork for us. */
+# define VFORK_STRING "fork"
 #else
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
+# define VFORK_STRING "vfork"
+#endif
+#ifdef HAVE_VFORK_H
+#include <vfork.h>
 #endif
+#ifdef VMS
+#define vfork() (decc$$alloc_vfork_blocks() >= 0 ? \
+               lib$get_current_invo_context(decc$$get_vfork_jmpbuf()) : -1)
+#endif /* VMS */
+
+#ifndef LIBRARY_PATH_ENV
+#define LIBRARY_PATH_ENV "LIBRARY_PATH"
 #endif
 
 #define COLLECT
 
+#include "collect2.h"
 #include "demangle.h"
 #include "obstack.h"
-#include "gansidecl.h"
-
-#ifndef errno
-extern int errno;
-#endif
-
-#ifndef HAVE_STRERROR
-extern char *sys_errlist[];
-extern int sys_nerr;
-#else
-char *strerror();
-#endif
+#include "intl.h"
+#include "version.h"
 
 /* Obstack allocation and deallocation routines.  */
 #define obstack_chunk_alloc xmalloc
 #define obstack_chunk_free free
-
-#ifdef USG
-#define vfork fork
-#endif
-
-#ifndef R_OK
-#define R_OK 4
-#define W_OK 2
-#define X_OK 1
-#endif
-
-#ifndef WIFSIGNALED
-#define WIFSIGNALED(S) (((S) & 0xff) != 0 && ((S) & 0xff) != 0x7f)
-#endif
-#ifndef WTERMSIG
-#define WTERMSIG(S) ((S) & 0x7f)
-#endif
-#ifndef WIFEXITED
-#define WIFEXITED(S) (((S) & 0xff) == 0)
-#endif
-#ifndef WEXITSTATUS
-#define WEXITSTATUS(S) (((S) & 0xff00) >> 8)
-#endif
-
-extern char *choose_temp_base ();
 \f
 /* On certain systems, we have code that works by scanning the object file
    directly.  But this code uses system-specific header files and library
@@ -171,7 +137,7 @@ extern char *choose_temp_base ();
 
 /* Default flags to pass to nm.  */
 #ifndef NM_FLAGS
-#define NM_FLAGS "-p"
+#define NM_FLAGS "-n"
 #endif
 
 #endif /* OBJECT_FORMAT_NONE */
@@ -185,6 +151,9 @@ extern char *choose_temp_base ();
 #define SYMBOL__MAIN __main
 #endif
 
+/* This must match tree.h.  */
+#define DEFAULT_INIT_PRIORITY 65535
+
 #if defined (LDD_SUFFIX) || SUNOS4_SHARED_LIBRARIES
 #define SCAN_LIBRARIES
 #endif
@@ -220,46 +189,37 @@ enum pass {
   PASS_SECOND                          /* with constructors linked in */
 };
 
-#ifndef NO_SYS_SIGLIST
-#ifndef SYS_SIGLIST_DECLARED
-extern char *sys_siglist[];
-#endif
-#endif
-extern char *version_string;
-
 int vflag;                             /* true if -v */
 static int rflag;                      /* true if -r */
 static int strip_flag;                 /* true if -s */
 #ifdef COLLECT_EXPORT_LIST
 static int export_flag;                 /* true if -bE */
+static int aix64_flag;                 /* true if -b64 */
 #endif
 
 int debug;                             /* true if -debug */
 
 static int shared_obj;                 /* true if -shared */
 
-static int   temp_filename_length;     /* Length of temp_filename */
-static char *temp_filename;            /* Base of temp filenames */
-static char *c_file;                   /* <xxx>.c for constructor/destructor list.  */
-static char *o_file;                   /* <xxx>.o for constructor/destructor list.  */
+static const char *c_file;             /* <xxx>.c for constructor/destructor list.  */
+static const char *o_file;             /* <xxx>.o for constructor/destructor list.  */
 #ifdef COLLECT_EXPORT_LIST
-static char *export_file;              /* <xxx>.x for AIX export list.  */
-static char *import_file;              /* <xxx>.p for AIX import list.  */
-#endif
-char *ldout;                           /* File for ld errors.  */
-static char *output_file;              /* Output file for ld.  */
-static char *nm_file_name;             /* pathname of nm */
-static char *ldd_file_name;            /* pathname of ldd (or equivalent) */
-static char *strip_file_name;          /* pathname of strip */
-char *c_file_name;                     /* pathname of gcc */
+static const char *export_file;                /* <xxx>.x for AIX export list.  */
+#endif
+const char *ldout;                     /* File for ld errors.  */
+static const char *output_file;                /* Output file for ld.  */
+static const char *nm_file_name;       /* pathname of nm */
+#ifdef LDD_SUFFIX
+static const char *ldd_file_name;      /* pathname of ldd (or equivalent) */
+#endif
+static const char *strip_file_name;            /* pathname of strip */
+const char *c_file_name;               /* pathname of gcc */
 static char *initname, *fininame;      /* names of init and fini funcs */
 
 static struct head constructors;       /* list of constructors found */
 static struct head destructors;                /* list of destructors found */
 #ifdef COLLECT_EXPORT_LIST
 static struct head exports;            /* list of exported symbols */
-static struct head imports;            /* list of imported symbols */
-static struct head undefined;          /* list of undefined symbols */
 #endif
 static struct head frame_tables;       /* list of frame unwind info tables */
 
@@ -267,19 +227,22 @@ struct obstack temporary_obstack;
 struct obstack permanent_obstack;
 char * temporary_firstobj;
 
+/* Holds the return value of pexecute.  */
+int pexecute_pid;
+
 /* Defined in the automatically-generated underscore.c.  */
 extern int prepends_underscore;
 
-extern char *getenv ();
-extern char *mktemp ();
-extern FILE *fdopen ();
+#ifndef GET_ENV_PATH_LIST
+#define GET_ENV_PATH_LIST(VAR,NAME)    do { (VAR) = getenv (NAME); } while (0)
+#endif
 
 /* Structure to hold all the directories in which to search for files to
    execute.  */
 
 struct prefix_list
 {
-  char *prefix;               /* String to prepend to the path.  */
+  const char *prefix;         /* String to prepend to the path.  */
   struct prefix_list *next;   /* Next in linked list.  */
 };
 
@@ -287,7 +250,7 @@ struct path_prefix
 {
   struct prefix_list *plist;  /* List of prefixes to try */
   int max_len;                /* Max length of a prefix in PLIST */
-  char *name;                 /* Name of this list (used in config stuff) */
+  const char *name;           /* Name of this list (used in config stuff) */
 };
 
 #ifdef COLLECT_EXPORT_LIST
@@ -297,55 +260,45 @@ static struct path_prefix cmdline_lib_dirs; /* directories specified with -L */
 static struct path_prefix libpath_lib_dirs; /* directories in LIBPATH */
 static struct path_prefix *libpaths[3] = {&cmdline_lib_dirs,
                                          &libpath_lib_dirs, NULL};
-static char *libexts[3] = {"a", "so", NULL};  /* possible library extentions */
-#endif
-
-void collect_exit              PROTO((int));
-void collect_execute           PROTO((char *, char **, char *));
-void dump_file                 PROTO((char *));
-static void handler            PROTO((int));
-static int is_ctor_dtor                PROTO((char *));
-static int is_in_prefix_list   PROTO((struct path_prefix *, char *, int));
-static char *find_a_file       PROTO((struct path_prefix *, char *));
-static void add_prefix         PROTO((struct path_prefix *, char *));
-static void prefix_from_env    PROTO((char *, struct path_prefix *));
-static void prefix_from_string PROTO((char *, struct path_prefix *));
-static void do_wait            PROTO((char *));
-static void fork_execute       PROTO((char *, char **));
-static void maybe_unlink       PROTO((char *));
-static void add_to_list                PROTO((struct head *, char *));
-static void write_list         PROTO((FILE *, char *, struct id *));
-static void dump_list          PROTO((FILE *, char *, struct id *));
-static void dump_prefix_list   PROTO((FILE *, char *, struct prefix_list *));
-static int is_in_list          PROTO((char *, struct id *));
-static void write_list_with_asm PROTO((FILE *, char *, struct id *));
-static void write_c_file       PROTO((FILE *, char *));
-static void scan_prog_file     PROTO((char *, enum pass));
-#ifdef SCAN_LIBRARIES
-static void scan_libraries     PROTO((char *));
-#endif
+static const char *libexts[3] = {"a", "so", NULL};  /* possible library extentions */
+#endif
+
+static void handler            PARAMS ((int));
+static int is_ctor_dtor                PARAMS ((const char *));
+static char *find_a_file       PARAMS ((struct path_prefix *, const char *));
+static void add_prefix         PARAMS ((struct path_prefix *, const char *));
+static void prefix_from_env    PARAMS ((const char *, struct path_prefix *));
+static void prefix_from_string PARAMS ((const char *, struct path_prefix *));
+static void do_wait            PARAMS ((const char *));
+static void fork_execute       PARAMS ((const char *, char **));
+static void maybe_unlink       PARAMS ((const char *));
+static void add_to_list                PARAMS ((struct head *, const char *));
+static int extract_init_priority PARAMS ((const char *));
+static void sort_ids           PARAMS ((struct head *));
+static void write_list         PARAMS ((FILE *, const char *, struct id *));
 #ifdef COLLECT_EXPORT_LIST
-static void write_export_file  PROTO((FILE *));
-static void write_import_file  PROTO((FILE *));
-static char *resolve_lib_name  PROTO((char *));
-static int use_import_list     PROTO((char *));
-static int ignore_library      PROTO((char *));
+static void dump_list          PARAMS ((FILE *, const char *, struct id *));
 #endif
-
-char *xcalloc ();
-char *xmalloc ();
-
-#ifdef NEED_DECLARATION_INDEX
-extern char *index ();
+#if 0
+static void dump_prefix_list   PARAMS ((FILE *, const char *, struct prefix_list *));
 #endif
-
-#ifdef NEED_DECLARATION_RINDEX
-extern char *rindex ();
+static void write_list_with_asm PARAMS ((FILE *, const char *, struct id *));
+static void write_c_file       PARAMS ((FILE *, const char *));
+static void write_c_file_stat  PARAMS ((FILE *, const char *));
+#ifndef LD_INIT_SWITCH
+static void write_c_file_glob  PARAMS ((FILE *, const char *));
 #endif
-
-#ifdef NEED_DECLARATION_FREE
-extern void free ();
+static void scan_prog_file     PARAMS ((const char *, enum pass));
+#ifdef SCAN_LIBRARIES
+static void scan_libraries     PARAMS ((const char *));
 #endif
+#ifdef COLLECT_EXPORT_LIST
+static int is_in_list          PARAMS ((const char *, struct id *));
+static void write_aix_file     PARAMS ((FILE *, struct id *));
+static char *resolve_lib_name  PARAMS ((const char *));
+static int ignore_library      PARAMS ((const char *));
+#endif
+static char *extract_string    PARAMS ((const char **));
 \f
 #ifdef NO_DUP2
 int
@@ -368,28 +321,6 @@ dup2 (oldfd, newfd)
   return fd;
 }
 #endif
-
-char *
-my_strerror (e)
-     int e;
-{
-
-#ifdef HAVE_STRERROR
-  return strerror (e);
-
-#else
-
-  static char buffer[30];
-  if (!e)
-    return "";
-
-  if (e > 0 && e < sys_nerr)
-    return sys_errlist[e];
-
-  sprintf (buffer, "Unknown error %d", e);
-  return buffer;
-#endif
-}
 \f
 /* Delete tempfiles and exit function.  */
 
@@ -406,9 +337,6 @@ collect_exit (status)
 #ifdef COLLECT_EXPORT_LIST
   if (export_file != 0 && export_file[0])
     maybe_unlink (export_file);
-
-  if (import_file != 0 && import_file[0])
-    maybe_unlink (import_file);
 #endif
 
   if (ldout != 0 && ldout[0])
@@ -424,41 +352,94 @@ collect_exit (status)
 }
 
 \f
+/* Notify user of a non-error.  */
+void
+notice VPARAMS ((const char *msgid, ...))
+{
+#ifndef ANSI_PROTOTYPES
+  const char *msgid;
+#endif
+  va_list ap;
+
+  VA_START (ap, msgid);
+
+#ifndef ANSI_PROTOTYPES
+  msgid = va_arg (ap, const char *);
+#endif
+
+  vfprintf (stderr, _(msgid), ap);
+  va_end (ap);
+}
+
 /* Die when sys call fails.  */
 
 void
-fatal_perror (string, arg1, arg2, arg3)
-     char *string, *arg1, *arg2, *arg3;
+fatal_perror VPARAMS ((const char * msgid, ...))
 {
+#ifndef ANSI_PROTOTYPES
+  const char *msgid;
+#endif
   int e = errno;
+  va_list ap;
+
+  VA_START (ap, msgid);
+
+#ifndef ANSI_PROTOTYPES
+  msgid = va_arg (ap, const char *);
+#endif
 
   fprintf (stderr, "collect2: ");
-  fprintf (stderr, string, arg1, arg2, arg3);
-  fprintf (stderr, ": %s\n", my_strerror (e));
+  vfprintf (stderr, _(msgid), ap);
+  fprintf (stderr, ": %s\n", xstrerror (e));
+  va_end (ap);
+
   collect_exit (FATAL_EXIT_CODE);
 }
 
 /* Just die.  */
 
 void
-fatal (string, arg1, arg2, arg3)
-     char *string, *arg1, *arg2, *arg3;
+fatal VPARAMS ((const char * msgid, ...))
 {
+#ifndef ANSI_PROTOTYPES
+  const char *msgid;
+#endif
+  va_list ap;
+  
+  VA_START (ap, msgid);
+
+#ifndef ANSI_PROTOTYPES
+  msgid = va_arg (ap, const char *);
+#endif
+  
   fprintf (stderr, "collect2: ");
-  fprintf (stderr, string, arg1, arg2, arg3);
+  vfprintf (stderr, _(msgid), ap);
   fprintf (stderr, "\n");
+  va_end (ap);
+
   collect_exit (FATAL_EXIT_CODE);
 }
 
 /* Write error message.  */
 
 void
-error (string, arg1, arg2, arg3, arg4)
-     char *string, *arg1, *arg2, *arg3, *arg4;
+error VPARAMS ((const char * msgid, ...))
 {
+#ifndef ANSI_PROTOTYPES
+  const char * msgid;
+#endif
+  va_list ap;
+  VA_START (ap, msgid);
+  
+#ifndef ANSI_PROTOTYPES
+  msgid = va_arg (ap, const char *);
+#endif
+
   fprintf (stderr, "collect2: ");
-  fprintf (stderr, string, arg1, arg2, arg3, arg4);
+  vfprintf (stderr, _(msgid), ap);
   fprintf (stderr, "\n");
+  va_end(ap);
 }
 
 /* In case obstack is linked in, and abort is defined to fancy_abort,
@@ -469,7 +450,6 @@ fancy_abort ()
 {
   fatal ("internal error");
 }
-
 \f
 static void
 handler (signo)
@@ -487,9 +467,6 @@ handler (signo)
 #ifdef COLLECT_EXPORT_LIST
   if (export_file != 0 && export_file[0])
     maybe_unlink (export_file);
-
-  if (import_file != 0 && import_file[0])
-    maybe_unlink (import_file);
 #endif
 
   signal (signo, SIG_DFL);
@@ -497,68 +474,20 @@ handler (signo)
 }
 
 \f
-char *
-xcalloc (size1, size2)
-     int size1, size2;
-{
-  char *ptr = (char *) calloc (size1, size2);
-  if (ptr)
-    return ptr;
-
-  fatal ("out of memory");
-  return (char *) 0;
-}
-
-char *
-xmalloc (size)
-     unsigned size;
-{
-  char *ptr = (char *) malloc (size);
-  if (ptr)
-    return ptr;
-
-  fatal ("out of memory");
-  return (char *) 0;
-}
-
-char *
-xrealloc (ptr, size)
-     char *ptr;
-     unsigned size;
-{
-  register char *value = (char *) realloc (ptr, size);
-  if (value == 0)
-    fatal ("virtual memory exhausted");
-  return value;
-}
-
 int
 file_exists (name)
-     char *name;
+     const char *name;
 {
   return access (name, R_OK) == 0;
 }
 
-/* Make a copy of a string INPUT with size SIZE.  */
-
-char *
-savestring (input, size)
-     char *input;
-     int size;
-{
-  char *output = (char *) xmalloc (size + 1);
-  bcopy (input, output, size);
-  output[size] = 0;
-  return output;
-}
-
 /* Parse a reasonable subset of shell quoting syntax.  */
 
 static char *
 extract_string (pp)
-     char **pp;
+     const char **pp;
 {
-  char *p = *pp;
+  const char *p = *pp;
   int backquote = 0;
   int inside = 0;
 
@@ -587,7 +516,7 @@ extract_string (pp)
 \f
 void
 dump_file (name)
-     char *name;
+     const char *name;
 {
   FILE *stream = fopen (name, "r");
   int no_demangle = !! getenv ("COLLECT_NO_DEMANGLE");
@@ -598,11 +527,12 @@ dump_file (name)
     {
       int c;
       while (c = getc (stream),
-            c != EOF && (isalnum (c) || c == '_' || c == '$' || c == '.'))
+            c != EOF && (ISALNUM (c) || c == '_' || c == '$' || c == '.'))
        obstack_1grow (&temporary_obstack, c);
       if (obstack_object_size (&temporary_obstack) > 0)
        {
-         char *word, *p, *result;
+         const char *word, *p;
+         char *result;
          obstack_1grow (&temporary_obstack, '\0');
          word = obstack_finish (&temporary_obstack);
 
@@ -643,18 +573,20 @@ dump_file (name)
   fclose (stream);
 }
 \f
-/* Decide whether the given symbol is:
-   a constructor (1), a destructor (2), or neither (0).  */
+/* Decide whether the given symbol is: a constructor (1), a destructor
+   (2), a routine in a shared object that calls all the constructors
+   (3) or destructors (4), a DWARF exception-handling table (5), or
+   nothing special (0).  */
 
 static int
 is_ctor_dtor (s)
-     char *s;
+     const char *s;
 {
-  struct names { char *name; int len; int ret; int two_underscores; };
+  struct names { const char *name; int len; int ret; int two_underscores; };
 
   register struct names *p;
   register int ch;
-  register char *orig_s = s;
+  register const char *orig_s = s;
 
   static struct names special[] = {
 #ifdef NO_DOLLAR_IN_LABEL
@@ -703,59 +635,6 @@ is_ctor_dtor (s)
   return 0;
 }
 \f
-/* Routine to add variables to the environment.  */
-
-#ifndef HAVE_PUTENV
-
-int
-putenv (str)
-     char *str;
-{
-#ifndef VMS                    /* nor about VMS */
-
-  extern char **environ;
-  char **old_environ = environ;
-  char **envp;
-  int num_envs = 0;
-  int name_len = 1;
-  char *p = str;
-  int ch;
-
-  while ((ch = *p++) != '\0' && ch != '=')
-    name_len++;
-
-  if (!ch)
-    abort ();
-
-  /* Search for replacing an existing environment variable, and
-     count the number of total environment variables.  */
-  for (envp = old_environ; *envp; envp++)
-    {
-      num_envs++;
-      if (!strncmp (str, *envp, name_len))
-       {
-         *envp = str;
-         return 0;
-       }
-    }
-
-  /* Add a new environment variable */
-  environ = (char **) xmalloc (sizeof (char *) * (num_envs+2));
-  *environ = str;
-  bcopy ((char *) old_environ, (char *) (environ + 1),
-        sizeof (char *) * (num_envs+1));
-
-  return 0;
-#endif /* VMS */
-}
-
-#endif /* HAVE_PUTENV */
-\f
-/* By default, colon separates directories in a path.  */
-#ifndef PATH_SEPARATOR
-#define PATH_SEPARATOR ':'
-#endif
-
 /* We maintain two prefix lists: one from COMPILER_PATH environment variable
    and one from the PATH variable.  */
 
@@ -765,51 +644,9 @@ static struct path_prefix cpath, path;
 /* This is the name of the target machine.  We use it to form the name
    of the files to execute.  */
 
-static char *target_machine = TARGET_MACHINE;
+static const char *const target_machine = TARGET_MACHINE;
 #endif
 
-/* Names under which we were executed.  Never return one of those files in our
-   searches.  */
-
-static struct path_prefix our_file_names;
-\f
-/* Determine if STRING is in PPREFIX.
-
-   This utility is currently only used to look up file names.  Prefix lists
-   record directory names.  This matters to us because the latter has a 
-   trailing slash, so I've added a flag to handle both.  */
-
-static int
-is_in_prefix_list (pprefix, string, filep)
-     struct path_prefix *pprefix;
-     char *string;
-     int filep;
-{
-  struct prefix_list *pl;
-
-  if (filep)
-    {
-      int len = strlen (string);
-
-      for (pl = pprefix->plist; pl; pl = pl->next)
-       {
-         if (strncmp (pl->prefix, string, len) == 0
-             && strcmp (pl->prefix + len, "/") == 0)
-           return 1;
-       }
-    }
-  else
-    {
-      for (pl = pprefix->plist; pl; pl = pl->next)
-       {
-         if (strcmp (pl->prefix, string) == 0)
-           return 1;
-       }
-    }
-
-  return 0;
-}
-
 /* Search for NAME using prefix list PPREFIX.  We only look for executable
    files. 
 
@@ -818,12 +655,15 @@ is_in_prefix_list (pprefix, string, filep)
 static char *
 find_a_file (pprefix, name)
      struct path_prefix *pprefix;
-     char *name;
+     const char *name;
 {
   char *temp;
   struct prefix_list *pl;
   int len = pprefix->max_len + strlen (name) + 1;
 
+  if (debug)
+    fprintf (stderr, "Looking for '%s'\n", name);
+  
 #ifdef EXECUTABLE_SUFFIX
   len += strlen (EXECUTABLE_SUFFIX);
 #endif
@@ -832,22 +672,45 @@ find_a_file (pprefix, name)
 
   /* Determine the filename to execute (special case for absolute paths).  */
 
-  if (*name == '/')
+  if (*name == '/'
+#ifdef HAVE_DOS_BASED_FILE_SYSTEM
+      || (*name && name[1] == ':')
+#endif
+      )
     {
       if (access (name, X_OK) == 0)
        {
          strcpy (temp, name);
+
+         if (debug)
+           fprintf (stderr, "  - found: absolute path\n");
+         
          return temp;
        }
+
+#ifdef EXECUTABLE_SUFFIX
+       /* Some systems have a suffix for executable files.
+          So try appending that.  */
+      strcpy (temp, name);
+       strcat (temp, EXECUTABLE_SUFFIX);
+       
+       if (access (temp, X_OK) == 0)
+         return temp;
+#endif
+
+      if (debug)
+       fprintf (stderr, "  - failed to locate using absolute path\n");
     }
   else
     for (pl = pprefix->plist; pl; pl = pl->next)
       {
+       struct stat st;
+
        strcpy (temp, pl->prefix);
        strcat (temp, name);
-       if (! is_in_prefix_list (&our_file_names, temp, 1)
-           /* This is a kludge, but there seems no way around it.  */
-           && strcmp (temp, "./ld") != 0
+       
+       if (stat (temp, &st) >= 0
+           && ! S_ISDIR (st.st_mode)
            && access (temp, X_OK) == 0)
          return temp;
 
@@ -855,12 +718,17 @@ find_a_file (pprefix, name)
        /* Some systems have a suffix for executable files.
           So try appending that.  */
        strcat (temp, EXECUTABLE_SUFFIX);
-       if (! is_in_prefix_list (&our_file_names, temp, 1)
+       
+       if (stat (temp, &st) >= 0
+           && ! S_ISDIR (st.st_mode)
            && access (temp, X_OK) == 0)
          return temp;
 #endif
       }
 
+  if (debug && pprefix->plist == NULL)
+    fprintf (stderr, "  - failed: no entries in prefix list\n");
+
   free (temp);
   return 0;
 }
@@ -870,7 +738,7 @@ find_a_file (pprefix, name)
 static void
 add_prefix (pprefix, prefix)
      struct path_prefix *pprefix;
-     char *prefix;
+     const char *prefix;
 {
   struct prefix_list *pl, **prev;
   int len;
@@ -891,7 +759,7 @@ add_prefix (pprefix, prefix)
     pprefix->max_len = len;
 
   pl = (struct prefix_list *) xmalloc (sizeof (struct prefix_list));
-  pl->prefix = savestring (prefix, len);
+  pl->prefix = xstrdup (prefix);
 
   if (*prev)
     pl->next = *prev;
@@ -905,10 +773,11 @@ add_prefix (pprefix, prefix)
 
 static void
 prefix_from_env (env, pprefix)
-     char *env;
+     const char *env;
      struct path_prefix *pprefix;
 {
-  char *p = getenv (env);
+  const char *p;
+  GET_ENV_PATH_LIST (p, env);
 
   if (p)
     prefix_from_string (p, pprefix);
@@ -916,12 +785,15 @@ prefix_from_env (env, pprefix)
 
 static void
 prefix_from_string (p, pprefix)
-     char *p;
+     const char *p;
      struct path_prefix *pprefix;
 {
-  char *startp, *endp;
+  const char *startp, *endp;
   char *nstore = (char *) xmalloc (strlen (p) + 3);
 
+  if (debug)
+    fprintf (stderr, "Convert string '%s' into prefixes, separator = '%c'\n", p, PATH_SEPARATOR);
+  
   startp = endp = p;
   while (1)
     {
@@ -932,14 +804,17 @@ prefix_from_string (p, pprefix)
            {
              strcpy (nstore, "./");
            }
-         else if (endp[-1] != '/')
+         else if (! IS_DIR_SEPARATOR (endp[-1]))
            {
-             nstore[endp-startp] = '/';
+             nstore[endp-startp] = DIR_SEPARATOR;
              nstore[endp-startp+1] = 0;
            }
          else
            nstore[endp-startp] = 0;
 
+         if (debug)
+           fprintf (stderr, "  - add prefix: %s\n", nstore);
+         
          add_prefix (pprefix, nstore);
          if (*endp == 0)
            break;
@@ -952,56 +827,93 @@ prefix_from_string (p, pprefix)
 \f
 /* Main program.  */
 
+int main               PARAMS ((int, char *[]));
 int
 main (argc, argv)
      int argc;
      char *argv[];
 {
-  char *ld_suffix      = "ld";
-  char *full_ld_suffix = ld_suffix;
-  char *real_ld_suffix = "real-ld";
-#ifdef CROSS_COMPILE
-  char *full_real_ld_suffix = real_ld_suffix;
-#endif
-  char *collect_ld_suffix = "collect-ld";
-  char *nm_suffix      = "nm";
-  char *full_nm_suffix = nm_suffix;
-  char *gnm_suffix     = "gnm";
-  char *full_gnm_suffix        = gnm_suffix;
+  const char *ld_suffix        = "ld";
+  const char *full_ld_suffix   = ld_suffix;
+  const char *real_ld_suffix   = "real-ld";
+  const char *collect_ld_suffix = "collect-ld";
+  const char *nm_suffix        = "nm";
+  const char *full_nm_suffix   = nm_suffix;
+  const char *gnm_suffix       = "gnm";
+  const char *full_gnm_suffix  = gnm_suffix;
 #ifdef LDD_SUFFIX
-  char *ldd_suffix     = LDD_SUFFIX;
-  char *full_ldd_suffix        = ldd_suffix;
-#endif
-  char *strip_suffix   = "strip";
-  char *full_strip_suffix = strip_suffix;
-  char *gstrip_suffix  = "gstrip";
-  char *full_gstrip_suffix = gstrip_suffix;
-  char *arg;
+  const char *ldd_suffix       = LDD_SUFFIX;
+  const char *full_ldd_suffix  = ldd_suffix;
+#endif
+  const char *strip_suffix     = "strip";
+  const char *full_strip_suffix = strip_suffix;
+  const char *gstrip_suffix    = "gstrip";
+  const char *full_gstrip_suffix = gstrip_suffix;
+  const char *arg;
   FILE *outf;
 #ifdef COLLECT_EXPORT_LIST
   FILE *exportf;
-  FILE *importf;
 #endif
-  char *ld_file_name;
-  char *collect_name;
-  char *collect_names;
-  char *p;
+  const char *ld_file_name;
+  const char *p;
   char **c_argv;
-  char **c_ptr;
-  char **ld1_argv      = (char **) xcalloc (sizeof (char *), argc+3);
-  char **ld1           = ld1_argv;
-  char **ld2_argv      = (char **) xcalloc (sizeof (char *), argc+6);
-  char **ld2           = ld2_argv;
-  char **object_lst    = (char **) xcalloc (sizeof (char *), argc);
-  char **object                = object_lst;
+  const char **c_ptr;
+  char **ld1_argv;
+  const char **ld1;
+  char **ld2_argv;
+  const char **ld2;
+  char **object_lst;
+  const char **object;
   int first_file;
-  int num_c_args       = argc+7;
+  int num_c_args       = argc+9;
+
+#if defined (COLLECT2_HOST_INITIALIZATION)
+  /* Perform system dependent initialization, if neccessary.  */
+  COLLECT2_HOST_INITIALIZATION;
+#endif
+
+#ifdef SIGCHLD
+  /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will
+     receive the signal.  A different setting is inheritable */
+  signal (SIGCHLD, SIG_DFL);
+#endif
+
+/* LC_CTYPE determines the character set used by the terminal so it has be set
+   to output messages correctly.  */
+
+#ifdef HAVE_LC_MESSAGES
+  setlocale (LC_CTYPE, "");
+  setlocale (LC_MESSAGES, "");
+#else
+  setlocale (LC_ALL, "");
+#endif
+
+  (void) bindtextdomain (PACKAGE, localedir);
+  (void) textdomain (PACKAGE);
+
+  /* Do not invoke xcalloc before this point, since locale needs to be
+     set first, in case a diagnostic is issued.  */
+
+  ld1 = (const char **)(ld1_argv = (char **) xcalloc(sizeof (char *), argc+3));
+  ld2 = (const char **)(ld2_argv = (char **) xcalloc(sizeof (char *), argc+10));
+  object = (const char **)(object_lst = (char **) xcalloc(sizeof (char *), argc));
 
 #ifdef DEBUG
   debug = 1;
-  vflag = 1;
 #endif
 
+  /* Parse command line early for instances of -debug.  This allows
+     the debug flag to be set before functions like find_a_file()
+     are called.  */
+  {
+    int i;
+    
+    for (i = 1; argv[i] != NULL; i ++)
+      if (! strcmp (argv[i], "-debug"))
+       debug = 1;
+    vflag = debug;
+  }
+
 #ifndef DEFAULT_A_OUT_NAME
   output_file = "a.out";
 #else
@@ -1011,62 +923,22 @@ main (argc, argv)
   obstack_begin (&temporary_obstack, 0);
   obstack_begin (&permanent_obstack, 0);
   temporary_firstobj = (char *) obstack_alloc (&temporary_obstack, 0);
-  current_demangling_style = gnu_demangling;
-
-  /* We must check that we do not call ourselves in an infinite
-     recursion loop. We append the name used for us to the COLLECT_NAMES
-     environment variable.
-
-     In practice, collect will rarely invoke itself.  This can happen now
-     that we are no longer called gld.  A perfect example is when running
-     gcc in a build directory that has been installed.  When looking for
-     ld, we will find our installed version and believe that's the real ld.  */
-
-  /* We must also append COLLECT_NAME to COLLECT_NAMES to watch for the
-     previous version of collect (the one that used COLLECT_NAME and only
-     handled two levels of recursion).  If we do not we may mutually recurse
-     forever.  This can happen (I think) when bootstrapping the old version
-     and a new one is installed (rare, but we should handle it).
-     ??? Hopefully references to COLLECT_NAME can be removed at some point.  */
-
-  collect_name = (char *) getenv ("COLLECT_NAME");
-  collect_names = (char *) getenv ("COLLECT_NAMES");
-
-  p = (char *) xmalloc (strlen ("COLLECT_NAMES=")
-                       + (collect_name ? strlen (collect_name) + 1 : 0)
-                       + (collect_names ? strlen (collect_names) + 1 : 0)
-                       + strlen (argv[0]) + 1);
-  strcpy (p, "COLLECT_NAMES=");
-  if (collect_name != 0)
-    sprintf (p + strlen (p), "%s%c", collect_name, PATH_SEPARATOR);
-  if (collect_names != 0)
-    sprintf (p + strlen (p), "%s%c", collect_names, PATH_SEPARATOR);
-  strcat (p, argv[0]);
-  putenv (p);
-
-  prefix_from_env ("COLLECT_NAMES", &our_file_names);
-
-  /* Set environment variable COLLECT_NAME to our name so the previous version
-     of collect will not find us.  If it does we will mutually recurse forever.
-     This can happen when bootstrapping the new version and an old version is
-     installed.
-     ??? Hopefully this bit of code can be removed at some point.  */
-
-  p = xmalloc (strlen ("COLLECT_NAME=") + strlen (argv[0]) + 1);
-  sprintf (p, "COLLECT_NAME=%s", argv[0]);
-  putenv (p);
-
-  p = (char *) getenv ("COLLECT_GCC_OPTIONS");
+
+  current_demangling_style = auto_demangling;
+  p = getenv ("COLLECT_GCC_OPTIONS");
   while (p && *p)
     {
-      char *q = extract_string (&p);
+      const char *q = extract_string (&p);
       if (*q == '-' && (q[1] == 'm' || q[1] == 'f'))
        num_c_args++;
     }
   obstack_free (&temporary_obstack, temporary_firstobj);
-  ++num_c_args;
 
-  c_ptr = c_argv = (char **) xcalloc (sizeof (char *), num_c_args);
+  /* -fno-exceptions -w */
+  num_c_args += 2;
+
+  c_ptr = (const char **)
+    (c_argv = (char **) xcalloc (sizeof (char *), num_c_args));
 
   if (argc < 2)
     fatal ("no arguments");
@@ -1099,65 +971,37 @@ main (argc, argv)
 #ifdef CROSS_COMPILE
   /* If we look for a program in the compiler directories, we just use
      the short name, since these directories are already system-specific.
-     But it we look for a took in the system directories, we need to
+     But it we look for a program in the system directories, we need to
      qualify the program name with the target machine.  */
 
-  full_ld_suffix
-    = xcalloc (strlen (ld_suffix) + strlen (target_machine) + 2, 1);
-  strcpy (full_ld_suffix, target_machine);
-  strcat (full_ld_suffix, "-");
-  strcat (full_ld_suffix, ld_suffix);
-
-  full_real_ld_suffix
-    = xcalloc (strlen (real_ld_suffix) + strlen (target_machine) + 2, 1);
-  strcpy (full_real_ld_suffix, target_machine);
-  strcat (full_real_ld_suffix, "-");
-  strcat (full_real_ld_suffix, real_ld_suffix);
+  full_ld_suffix = concat(target_machine, "-", ld_suffix, NULL);
 
 #if 0
-  full_gld_suffix
-    = xcalloc (strlen (gld_suffix) + strlen (target_machine) + 2, 1);
-  strcpy (full_gld_suffix, target_machine);
-  strcat (full_gld_suffix, "-");
-  strcat (full_gld_suffix, gld_suffix);
+  full_gld_suffix = concat (target_machine, "-", gld_suffix, NULL);
 #endif
 
-  full_nm_suffix
-    = xcalloc (strlen (nm_suffix) + strlen (target_machine) + 2, 1);
-  strcpy (full_nm_suffix, target_machine);
-  strcat (full_nm_suffix, "-");
-  strcat (full_nm_suffix, nm_suffix);
-
-  full_gnm_suffix
-    = xcalloc (strlen (gnm_suffix) + strlen (target_machine) + 2, 1);
-  strcpy (full_gnm_suffix, target_machine);
-  strcat (full_gnm_suffix, "-");
-  strcat (full_gnm_suffix, gnm_suffix);
+  full_nm_suffix = concat (target_machine, "-", nm_suffix, NULL);
 
+  full_gnm_suffix = concat (target_machine, "-", gnm_suffix, NULL);
+  
 #ifdef LDD_SUFFIX
-  full_ldd_suffix
-    = xcalloc (strlen (ldd_suffix) + strlen (target_machine) + 2, 1);
-  strcpy (full_ldd_suffix, target_machine);
-  strcat (full_ldd_suffix, "-");
-  strcat (full_ldd_suffix, ldd_suffix);
-#endif
-
-  full_strip_suffix
-    = xcalloc (strlen (strip_suffix) + strlen (target_machine) + 2, 1);
-  strcpy (full_strip_suffix, target_machine);
-  strcat (full_strip_suffix, "-");
-  strcat (full_strip_suffix, strip_suffix);
+  full_ldd_suffix = concat (target_machine, "-", ldd_suffix, NULL);
+#endif
+
+  full_strip_suffix = concat (target_machine, "-", strip_suffix, NULL);
   
-  full_gstrip_suffix
-    = xcalloc (strlen (gstrip_suffix) + strlen (target_machine) + 2, 1);
-  strcpy (full_gstrip_suffix, target_machine);
-  strcat (full_gstrip_suffix, "-");
-  strcat (full_gstrip_suffix, gstrip_suffix);
+  full_gstrip_suffix = concat (target_machine, "-", gstrip_suffix, NULL);
 #endif /* CROSS_COMPILE */
 
   /* Try to discover a valid linker/nm/strip to use.  */
 
   /* Maybe we know the right file to use (if not cross).  */
+  ld_file_name = 0;
+#ifdef DEFAULT_LINKER
+  if (access (DEFAULT_LINKER, X_OK) == 0)
+    ld_file_name = DEFAULT_LINKER;
+  if (ld_file_name == 0)
+#endif
 #ifdef REAL_LD_FILE_NAME
   ld_file_name = find_a_file (&path, REAL_LD_FILE_NAME);
   if (ld_file_name == 0)
@@ -1176,18 +1020,6 @@ main (argc, argv)
   if (ld_file_name == 0)
     ld_file_name = find_a_file (&path, full_ld_suffix);
 
-  /* If we've invoked ourselves, try again with LD_FILE_NAME.  */
-
-  if (collect_names != 0)
-    {
-      if (ld_file_name != 0)
-       {
-         argv[0] = ld_file_name;
-         execvp (argv[0], argv);
-       }
-      fatal ("cannot find `ld'");
-    }
-
 #ifdef REAL_NM_FILE_NAME
   nm_file_name = find_a_file (&path, REAL_NM_FILE_NAME);
   if (nm_file_name == 0)
@@ -1223,9 +1055,7 @@ main (argc, argv)
   if (c_file_name == 0)
     {
 #ifdef CROSS_COMPILE
-      c_file_name = xcalloc (sizeof ("gcc-") + strlen (target_machine) + 1, 1);
-      strcpy (c_file_name, target_machine);
-      strcat (c_file_name, "-gcc");
+      c_file_name = concat (target_machine, "-gcc", NULL);
 #else
       c_file_name = "gcc";
 #endif
@@ -1244,23 +1074,15 @@ main (argc, argv)
   *ld1++ = *ld2++ = ld_file_name;
 
   /* Make temp file names.  */
-  temp_filename = choose_temp_base ();
-  temp_filename_length = strlen (temp_filename);
-  c_file = xcalloc (temp_filename_length + sizeof (".c"), 1);
-  o_file = xcalloc (temp_filename_length + sizeof (".o"), 1);
-#ifdef COLLECT_EXPORT_LIST
-  export_file = xmalloc (temp_filename_length + sizeof (".x"));
-  import_file = xmalloc (temp_filename_length + sizeof (".p"));
-#endif
-  ldout = xmalloc (temp_filename_length + sizeof (".ld"));
-  sprintf (ldout, "%s.ld", temp_filename);
-  sprintf (c_file, "%s.c", temp_filename);
-  sprintf (o_file, "%s.o", temp_filename);
+  c_file = make_temp_file (".c");
+  o_file = make_temp_file (".o");
 #ifdef COLLECT_EXPORT_LIST
-  sprintf (export_file, "%s.x", temp_filename);
-  sprintf (import_file, "%s.p", temp_filename);
+  export_file = make_temp_file (".x");
 #endif
+  ldout = make_temp_file (".ld");
   *c_ptr++ = c_file_name;
+  *c_ptr++ = "-x";
+  *c_ptr++ = "c";
   *c_ptr++ = "-c";
   *c_ptr++ = "-o";
   *c_ptr++ = o_file;
@@ -1279,17 +1101,29 @@ main (argc, argv)
      AIX support needs to know if -shared has been specified before
      parsing commandline arguments.  */
 
-  p = (char *) getenv ("COLLECT_GCC_OPTIONS");
+  p = getenv ("COLLECT_GCC_OPTIONS");
   while (p && *p)
     {
-      char *q = extract_string (&p);
+      const char *q = extract_string (&p);
       if (*q == '-' && (q[1] == 'm' || q[1] == 'f'))
        *c_ptr++ = obstack_copy0 (&permanent_obstack, q, strlen (q));
+      if (strcmp (q, "-EL") == 0 || strcmp (q, "-EB") == 0)
+       *c_ptr++ = obstack_copy0 (&permanent_obstack, q, strlen (q));
       if (strncmp (q, "-shared", sizeof ("-shared") - 1) == 0)
        shared_obj = 1;
+      if (*q == '-' && q[1] == 'B')
+       {
+         *c_ptr++ = obstack_copy0 (&permanent_obstack, q, strlen (q));
+         if (q[2] == 0)
+           {
+             q = extract_string (&p);
+             *c_ptr++ = obstack_copy0 (&permanent_obstack, q, strlen (q));
+           }
+       }
     }
   obstack_free (&temporary_obstack, temporary_firstobj);
   *c_ptr++ = "-fno-exceptions";
+  *c_ptr++ = "-w";
 
   /* !!! When GCC calls collect2,
      it does not know whether it is calling collect2 or ld.
@@ -1316,14 +1150,15 @@ main (argc, argv)
            case 'b':
              if (arg[2] == 'E' || strncmp (&arg[2], "export", 6) == 0)
                 export_flag = 1;
+             else if (arg[2] == '6' && arg[3] == '4')
+               aix64_flag = 1;
              break;
 #endif
 
            case 'd':
              if (!strcmp (arg, "-debug"))
                {
-                 debug = 1;
-                 vflag = 1;
+                 /* Already parsed.  */
                  ld1--;
                  ld2--;
                }
@@ -1341,15 +1176,7 @@ main (argc, argv)
 #ifdef COLLECT_EXPORT_LIST
              {
                /* Resolving full library name.  */
-               char *s = resolve_lib_name (arg+2);
-
-               /* If we will use an import list for this library,
-                  we should exclude it from ld args.  */
-               if (use_import_list (s))
-                 {
-                   ld1--;
-                   ld2--;
-                 }
+               const char *s = resolve_lib_name (arg+2);
 
                /* Saving a full library name.  */
                add_to_list (&libs, s);
@@ -1367,7 +1194,12 @@ main (argc, argv)
            case 'o':
              if (arg[2] == '\0')
                output_file = *ld1++ = *ld2++ = *++argv;
-             else
+             else if (1
+#ifdef SWITCHES_NEED_SPACES
+                      && ! strchr (SWITCHES_NEED_SPACES, arg[1])
+#endif
+                      )
+
                output_file = &arg[2];
              break;
 
@@ -1393,9 +1225,10 @@ main (argc, argv)
              break;
            }
        }
-      else if ((p = rindex (arg, '.')) != (char *) 0
+      else if ((p = strrchr (arg, '.')) != (char *) 0
               && (strcmp (p, ".o") == 0 || strcmp (p, ".a") == 0
-                  || strcmp (p, ".so") == 0))
+                  || strcmp (p, ".so") == 0 || strcmp (p, ".lo") == 0
+                  || strcmp (p, ".obj") == 0))
        {
          if (first_file)
            {
@@ -1410,20 +1243,12 @@ main (argc, argv)
                  *ld2++ = arg;
                }
            }
-         if (p[1] == 'o')
+         if (p[1] == 'o' || p[1] == 'l')
            *object++ = arg;
 #ifdef COLLECT_EXPORT_LIST
          /* libraries can be specified directly, i.e. without -l flag.  */
                  else
                    { 
-             /* If we will use an import list for this library,
-                we should exclude it from ld args.  */
-             if (use_import_list (arg))
-               {
-                 ld1--;
-                 ld2--;
-               }
-
              /* Saving a full library name.  */
               add_to_list (&libs, arg);
             }
@@ -1442,45 +1267,41 @@ main (argc, argv)
   /* The AIX linker will discard static constructors in object files if
      nothing else in the file is referenced, so look at them first.  */
   {
-      char **export_object_lst = object_lst;
+      const char **export_object_lst = (const char **)object_lst;
+
       while (export_object_lst < object)
        scan_prog_file (*export_object_lst++, PASS_OBJ);
   }
   {
     struct id *list = libs.first;
+
     for (; list; list = list->next)
       scan_prog_file (list->name, PASS_FIRST);
   }
-  {
-    char *buf1 = alloca (strlen (export_file) + 5);
-    char *buf2 = alloca (strlen (import_file) + 5);
-    sprintf (buf1, "-bE:%s", export_file);
-    sprintf (buf2, "-bI:%s", import_file);
-    *ld1++ = buf1;
-    *ld2++ = buf1;
-    *ld1++ = buf2;
-    *ld2++ = buf2;
-    exportf = fopen (export_file, "w");
-    if (exportf == (FILE *) 0)
-      fatal_perror ("%s", export_file);
-    write_export_file (exportf);
-    if (fclose (exportf))
-      fatal_perror ("closing %s", export_file);
-    importf = fopen (import_file, "w");
-    if (importf == (FILE *) 0)
-      fatal_perror ("%s", import_file);
-    write_import_file (importf);
-    if (fclose (importf))
-      fatal_perror ("closing %s", import_file);
-  }
+
+  if (exports.first)
+    {
+      char *buf = xmalloc (strlen (export_file) + 5);
+
+      sprintf (buf, "-bE:%s", export_file);
+      *ld1++ = buf;
+      *ld2++ = buf;
+
+      exportf = fopen (export_file, "w");
+      if (exportf == (FILE *) 0)
+       fatal_perror ("fopen %s", export_file);
+      write_aix_file (exportf, exports.first);
+      if (fclose (exportf))
+       fatal_perror ("fclose %s", export_file);
+    }
 #endif
 
   *c_ptr++ = c_file;
-  *object = *c_ptr = *ld1 = (char *) 0;
+  *c_ptr = *ld1 = *object = (char *) 0;
 
   if (vflag)
     {
-      fprintf (stderr, "collect2 version %s", version_string);
+      notice ("collect2 version %s", version_string);
 #ifdef TARGET_VERSION
       TARGET_VERSION;
 #endif
@@ -1489,7 +1310,7 @@ main (argc, argv)
 
   if (debug)
     {
-      char *ptr;
+      const char *ptr;
       fprintf (stderr, "ld_file_name        = %s\n",
               (ld_file_name ? ld_file_name : "not found"));
       fprintf (stderr, "c_file_name         = %s\n",
@@ -1507,10 +1328,6 @@ main (argc, argv)
       fprintf (stderr, "o_file              = %s\n",
               (o_file ? o_file : "not found"));
 
-      ptr = getenv ("COLLECT_NAMES");
-      if (ptr)
-       fprintf (stderr, "COLLECT_NAMES       = %s\n", ptr);
-
       ptr = getenv ("COLLECT_GCC_OPTIONS");
       if (ptr)
        fprintf (stderr, "COLLECT_GCC_OPTIONS = %s\n", ptr);
@@ -1523,9 +1340,9 @@ main (argc, argv)
       if (ptr)
        fprintf (stderr, "COMPILER_PATH       = %s\n", ptr);
 
-      ptr = getenv ("LIBRARY_PATH");
+      ptr = getenv (LIBRARY_PATH_ENV);
       if (ptr)
-       fprintf (stderr, "LIBRARY_PATH        = %s\n", ptr);
+       fprintf (stderr, "%-20s= %s\n", LIBRARY_PATH_ENV, ptr);
 
       fprintf (stderr, "\n");
     }
@@ -1535,27 +1352,35 @@ main (argc, argv)
 
   /* On AIX we do this later.  */
 #ifndef COLLECT_EXPORT_LIST
-  do_tlink (ld1_argv, object_lst); 
-#else
+  do_tlink (ld1_argv, object_lst);
+#endif
 
   /* If -r or they will be run via some other method, do not build the
      constructor or destructor list, just return now.  */
-  if (rflag || ! do_collecting)
+  if (rflag
+#ifndef COLLECT_EXPORT_LIST
+      || ! do_collecting
+#endif
+      )
     {
+#ifdef COLLECT_EXPORT_LIST
+      /* Do the link we avoided above if we are exiting.  */
+      do_tlink (ld1_argv, object_lst);
+
       /* But make sure we delete the export file we may have created.  */
       if (export_file != 0 && export_file[0])
        maybe_unlink (export_file);
-      if (import_file != 0 && import_file[0])
-       maybe_unlink (import_file);
+#endif
+      maybe_unlink (c_file);
+      maybe_unlink (o_file);
       return 0;
     }
-#endif
 
   /* Examine the namelist with nm and search it for static constructors
      and destructors to call.
      Write the constructor and destructor tables to a .s file and reload.  */
 
-  /* On AIX we already done scanning for global constructors/destructors.  */
+  /* On AIX we already scanned for global constructors/destructors.  */
 #ifndef COLLECT_EXPORT_LIST
   scan_prog_file (output_file, PASS_FIRST);
 #endif
@@ -1566,8 +1391,9 @@ main (argc, argv)
 
   if (debug)
     {
-      fprintf (stderr, "%d constructor(s) found\n", constructors.number);
-      fprintf (stderr, "%d destructor(s)  found\n", destructors.number);
+      notice ("%d constructor(s) found\n", constructors.number);
+      notice ("%d destructor(s)  found\n", destructors.number);
+      notice ("%d frame table(s) found\n", frame_tables.number);
     }
 
   if (constructors.number == 0 && destructors.number == 0
@@ -1581,61 +1407,90 @@ main (argc, argv)
       )
     {
 #ifdef COLLECT_EXPORT_LIST
-      /* Doing tlink without additional code generation */
+      /* Do tlink without additional code generation */
       do_tlink (ld1_argv, object_lst);
 #endif
       /* Strip now if it was requested on the command line.  */
       if (strip_flag)
        {
-         char **strip_argv = (char **) xcalloc (sizeof (char *), 3);
+         char **real_strip_argv = (char **) xcalloc (sizeof (char *), 3);
+         const char ** strip_argv = (const char **) real_strip_argv;
+         
          strip_argv[0] = strip_file_name;
          strip_argv[1] = output_file;
          strip_argv[2] = (char *) 0;
-         fork_execute ("strip", strip_argv);
+         fork_execute ("strip", real_strip_argv);
        }
 
 #ifdef COLLECT_EXPORT_LIST
       maybe_unlink (export_file);
-      maybe_unlink (import_file);
 #endif
+      maybe_unlink (c_file);
+      maybe_unlink (o_file);
       return 0;
     }
 
+  /* Sort ctor and dtor lists by priority. */
+  sort_ids (&constructors);
+  sort_ids (&destructors);
+
   maybe_unlink(output_file);
   outf = fopen (c_file, "w");
   if (outf == (FILE *) 0)
-    fatal_perror ("%s", c_file);
+    fatal_perror ("fopen %s", c_file);
 
   write_c_file (outf, c_file);
 
   if (fclose (outf))
-    fatal_perror ("closing %s", c_file);
+    fatal_perror ("fclose %s", c_file);
 
   /* Tell the linker that we have initializer and finalizer functions.  */
 #ifdef LD_INIT_SWITCH
+#ifdef COLLECT_EXPORT_LIST
+  {
+    /* option name + functions + colons + NULL */
+    char *buf = xmalloc (strlen (LD_INIT_SWITCH)
+                        + strlen(initname) + strlen(fininame) + 3);
+    sprintf (buf, "%s:%s:%s", LD_INIT_SWITCH, initname, fininame);
+    *ld2++ = buf;
+  }
+#else
   *ld2++ = LD_INIT_SWITCH;
   *ld2++ = initname;
   *ld2++ = LD_FINI_SWITCH;
   *ld2++ = fininame;
 #endif
-  *ld2 = (char*) 0;
+#endif
 
 #ifdef COLLECT_EXPORT_LIST
   if (shared_obj)
     {
+      /* If we did not add export flag to link arguments before, add it to
+        second link phase now.  No new exports should have been added.  */
+      if (! exports.first)
+       {
+         char *buf = xmalloc (strlen (export_file) + 5);
+
+         sprintf (buf, "-bE:%s", export_file);
+         *ld2++ = buf;
+       }
+
       add_to_list (&exports, initname);
       add_to_list (&exports, fininame);
       add_to_list (&exports, "_GLOBAL__DI");
       add_to_list (&exports, "_GLOBAL__DD");
       exportf = fopen (export_file, "w");
       if (exportf == (FILE *) 0)
-       fatal_perror ("%s", export_file);
-      write_export_file (exportf);
+       fatal_perror ("fopen %s", export_file);
+      write_aix_file (exportf, exports.first);
       if (fclose (exportf))
-       fatal_perror ("closing %s", export_file);
+       fatal_perror ("fclose %s", export_file);
     }
 #endif
 
+  /* End of arguments to second link phase.  */
+  *ld2 = (char*) 0;
+
   if (debug)
     {
       fprintf (stderr, "\n========== output_file = %s, c_file = %s\n",
@@ -1644,7 +1499,7 @@ main (argc, argv)
       fprintf (stderr, "========== end of c_file\n\n");
 #ifdef COLLECT_EXPORT_LIST
       fprintf (stderr, "\n========== export_file = %s\n", export_file);
-      write_export_file (stderr);
+      write_aix_file (stderr, exports.first);
       fprintf (stderr, "========== end of export_file\n\n");
 #endif
     }
@@ -1670,7 +1525,6 @@ main (argc, argv)
 
 #ifdef COLLECT_EXPORT_LIST
   maybe_unlink (export_file);
-  maybe_unlink (import_file);
 #endif
 
   return 0;
@@ -1681,29 +1535,19 @@ main (argc, argv)
 
 int
 collect_wait (prog)
-     char *prog;
+     const char *prog;
 {
   int status;
 
-  wait (&status);
+  pwait (pexecute_pid, &status, 0);
   if (status)
     {
       if (WIFSIGNALED (status))
        {
          int sig = WTERMSIG (status);
-#ifdef NO_SYS_SIGLIST
-         error ("%s terminated with signal %d %s",
-                prog,
-                sig,
-                (status & 0200) ? ", core dumped" : "");
-#else
          error ("%s terminated with signal %d [%s]%s",
-                prog,
-                sig,
-                sys_siglist[sig],
-                (status & 0200) ? ", core dumped" : "");
-#endif
-
+                prog, sig, strsignal(sig),
+                status & 0200 ? "" : ", core dumped");
          collect_exit (FATAL_EXIT_CODE);
        }
 
@@ -1715,7 +1559,7 @@ collect_wait (prog)
 
 static void
 do_wait (prog)
-     char *prog;
+     const char *prog;
 {
   int ret = collect_wait (prog);
   if (ret != 0)
@@ -1726,25 +1570,29 @@ do_wait (prog)
 }
 
 \f
-/* Fork and execute a program, and wait for the reply.  */
+/* Execute a program, and wait for the reply.  */
 
 void
 collect_execute (prog, argv, redir)
-     char *prog;
+     const char *prog;
      char **argv;
-     char *redir;
+     const char *redir;
 {
-  int pid;
+  char *errmsg_fmt;
+  char *errmsg_arg;
+  int redir_handle = -1;
+  int stdout_save = -1;
+  int stderr_save = -1;
 
   if (vflag || debug)
     {
       char **p_argv;
-      char *str;
+      const char *str;
 
       if (argv[0])
        fprintf (stderr, "%s", argv[0]);
       else
-       fprintf (stderr, "[cannot find %s]", prog);
+       notice ("[cannot find %s]", prog);
 
       for (p_argv = &argv[1]; (str = *p_argv) != (char *) 0; p_argv++)
        fprintf (stderr, " %s", str);
@@ -1761,35 +1609,46 @@ collect_execute (prog, argv, redir)
   if (argv[0] == 0)
     fatal ("cannot find `%s'", prog);
 
-  pid = vfork ();
-  if (pid == -1)
+  if (redir)
     {
-#ifdef vfork
-      fatal_perror ("fork");
-#else
-      fatal_perror ("vfork");
-#endif
+      /* Open response file.  */
+      redir_handle = open (redir, O_WRONLY | O_TRUNC | O_CREAT);
+
+      /* Duplicate the stdout and stderr file handles
+        so they can be restored later.  */
+      stdout_save = dup (STDOUT_FILENO);
+      if (stdout_save == -1)
+       fatal_perror ("redirecting stdout: %s", redir);
+      stderr_save = dup (STDERR_FILENO);
+      if (stderr_save == -1)
+       fatal_perror ("redirecting stdout: %s", redir);
+
+      /* Redirect stdout & stderr to our response file.  */
+      dup2 (redir_handle, STDOUT_FILENO);
+      dup2 (redir_handle, STDERR_FILENO);
     }
 
-  if (pid == 0)                        /* child context */
+  pexecute_pid = pexecute (argv[0], argv, argv[0], NULL,
+                          &errmsg_fmt, &errmsg_arg,
+                          (PEXECUTE_FIRST | PEXECUTE_LAST | PEXECUTE_SEARCH));
+
+  if (redir)
     {
-      if (redir)
-       {
-         unlink (redir);
-         if (freopen (redir, "a", stdout) == NULL)
-           fatal_perror ("redirecting stdout: %s", redir);
-         if (freopen (redir, "a", stderr) == NULL)
-           fatal_perror ("redirecting stderr: %s", redir);
-       }
+      /* Restore stdout and stderr to their previous settings.  */
+      dup2 (stdout_save, STDOUT_FILENO);
+      dup2 (stderr_save, STDERR_FILENO);
 
-      execvp (argv[0], argv);
-      fatal_perror ("executing %s", prog);
+      /* Close reponse file.  */
+      close (redir_handle);
     }
+
+ if (pexecute_pid == -1)
+   fatal_perror (errmsg_fmt, errmsg_arg);
 }
 
 static void
 fork_execute (prog, argv)
-     char *prog;
+     const char *prog;
      char **argv;
 {
   collect_execute (prog, argv, NULL);
@@ -1800,26 +1659,27 @@ fork_execute (prog, argv)
 
 static void
 maybe_unlink (file)
-     char *file;
+     const char *file;
 {
   if (!debug)
     unlink (file);
   else
-    fprintf (stderr, "[Leaving %s]\n", file);
+    notice ("[Leaving %s]\n", file);
 }
 
 \f
+static long sequence_number = 0;
+
 /* Add a name to a linked list.  */
 
 static void
 add_to_list (head_ptr, name)
      struct head *head_ptr;
-     char *name;
+     const char *name;
 {
   struct id *newid
     = (struct id *) xcalloc (sizeof (struct id) + strlen (name), 1);
   struct id *p;
-  static long sequence_number = 0;
   strcpy (newid->name, name);
 
   if (head_ptr->first)
@@ -1844,12 +1704,73 @@ add_to_list (head_ptr, name)
   head_ptr->number++;
 }
 
+/* Grab the init priority number from an init function name that
+   looks like "_GLOBAL_.I.12345.foo".  */
+
+static int
+extract_init_priority (name)
+     const char *name;
+{
+  int pos = 0, pri;
+
+  while (name[pos] == '_')
+    ++pos;
+  pos += 10; /* strlen ("GLOBAL__X_") */
+
+  /* Extract init_p number from ctor/dtor name. */
+  pri = atoi (name + pos);
+  return pri ? pri : DEFAULT_INIT_PRIORITY;
+}
+
+/* Insertion sort the ids from ctor/dtor list HEAD_PTR in descending order.
+   ctors will be run from right to left, dtors from left to right.  */
+
+static void
+sort_ids (head_ptr)
+     struct head *head_ptr;
+{
+  /* id holds the current element to insert.  id_next holds the next
+     element to insert.  id_ptr iterates through the already sorted elements
+     looking for the place to insert id.  */
+  struct id *id, *id_next, **id_ptr;
+
+  id = head_ptr->first;
+
+  /* We don't have any sorted elements yet.  */
+  head_ptr->first = NULL;
+
+  for (; id; id = id_next)
+    {
+      id_next = id->next;
+      id->sequence = extract_init_priority (id->name);
+
+      for (id_ptr = &(head_ptr->first); ; id_ptr = &((*id_ptr)->next))
+       if (*id_ptr == NULL
+           /* If the sequence numbers are the same, we put the id from the
+              file later on the command line later in the list.  */
+           || id->sequence > (*id_ptr)->sequence
+           /* Hack: do lexical compare, too.
+           || (id->sequence == (*id_ptr)->sequence
+               && strcmp (id->name, (*id_ptr)->name) > 0) */
+           )
+         {
+           id->next = *id_ptr;
+           *id_ptr = id;
+           break;
+         }
+    }
+
+  /* Now set the sequence numbers properly so write_c_file works.  */
+  for (id = head_ptr->first; id; id = id->next)
+    id->sequence = ++sequence_number;
+}
+
 /* Write: `prefix', the names on list LIST, `suffix'.  */
 
 static void
 write_list (stream, prefix, list)
      FILE *stream;
-     char *prefix;
+     const char *prefix;
      struct id *list;
 {
   while (list)
@@ -1859,10 +1780,11 @@ write_list (stream, prefix, list)
     }
 }
 
+#ifdef COLLECT_EXPORT_LIST
 /* This function is really used only on AIX, but may be useful.  */
 static int
 is_in_list (prefix, list)
-     char *prefix;
+     const char *prefix;
      struct id *list;
 {
   while (list)
@@ -1872,12 +1794,14 @@ is_in_list (prefix, list)
     }
     return 0;
 }
+#endif
 
 /* Added for debugging purpose.  */
+#ifdef COLLECT_EXPORT_LIST
 static void
 dump_list (stream, prefix, list)
      FILE *stream;
-     char *prefix;
+     const char *prefix;
      struct id *list;
 {
   while (list)
@@ -1886,11 +1810,13 @@ dump_list (stream, prefix, list)
       list = list->next;
     }
 }
+#endif
 
+#if 0
 static void
 dump_prefix_list (stream, prefix, list)
      FILE *stream;
-     char *prefix;
+     const char *prefix;
      struct prefix_list *list;
 {
   while (list)
@@ -1899,11 +1825,12 @@ dump_prefix_list (stream, prefix, list)
       list = list->next;
     }
 }
+#endif
 
 static void
 write_list_with_asm (stream, prefix, list)
      FILE *stream;
-     char *prefix;
+     const char *prefix;
      struct id *list;
 {
   while (list)
@@ -1920,21 +1847,22 @@ write_list_with_asm (stream, prefix, list)
 static void
 write_c_file_stat (stream, name)
      FILE *stream;
-     char *name;
+     const char *name ATTRIBUTE_UNUSED;
 {
-  char *prefix, *p, *q;
+  const char *p, *q;
+  char *prefix, *r;
   int frames = (frame_tables.number > 0);
 
   /* Figure out name of output_file, stripping off .so version.  */
-  p = rindex (output_file, '/');
+  p = strrchr (output_file, '/');
   if (p == 0)
-    p = (char *) output_file;
+    p = output_file;
   else
     p++;
   q = p;
   while (q)
     {
-      q = index (q,'.');
+      q = strchr (q,'.');
       if (q == 0)
        {
          q = p + strlen (p);
@@ -1955,12 +1883,12 @@ write_c_file_stat (stream, name)
   prefix = xmalloc (q - p + 1);
   strncpy (prefix, p, q - p);
   prefix[q - p] = 0;
-  for (q = prefix; *q; q++)
-    if (!isalnum (*q))
-      *q = '_';
+  for (r = prefix; *r; r++)
+    if (!ISALNUM ((unsigned char)*r))
+      *r = '_';
   if (debug)
-    fprintf (stderr, "\nwrite_c_file - output name is %s, prefix is %s\n",
-            output_file, prefix);
+    notice ("\nwrite_c_file - output name is %s, prefix is %s\n",
+           output_file, prefix);
 
 #define INIT_NAME_FORMAT "_GLOBAL__FI_%s"
   initname = xmalloc (strlen (prefix) + sizeof (INIT_NAME_FORMAT) - 2);
@@ -2051,10 +1979,11 @@ write_c_file_stat (stream, name)
 
 /* Write the constructor/destructor tables.  */
 
+#ifndef LD_INIT_SWITCH
 static void
 write_c_file_glob (stream, name)
      FILE *stream;
-     char *name;
+     const char *name ATTRIBUTE_UNUSED;
 {
   /* Write the tables as C code  */
 
@@ -2114,11 +2043,12 @@ write_c_file_glob (stream, name)
   fprintf (stream, "extern entry_pt %s;\n", NAME__MAIN);
   fprintf (stream, "entry_pt *__main_reference = %s;\n\n", NAME__MAIN);
 }
+#endif /* ! LD_INIT_SWITCH */
 
 static void
 write_c_file (stream, name)
      FILE *stream;
-     char *name;
+     const char *name;
 {
   fprintf (stream, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n");
 #ifndef LD_INIT_SWITCH
@@ -2132,22 +2062,15 @@ write_c_file (stream, name)
 
 #ifdef COLLECT_EXPORT_LIST
 static void
-write_export_file (stream)
-     FILE *stream;
-{
-  struct id *list = exports.first;
-  for (; list; list = list->next)
-    fprintf (stream, "%s\n", list->name);
-}
-
-static void
-write_import_file (stream)
+write_aix_file (stream, list)
      FILE *stream;
+     struct id *list;
 {
-  struct id *list = imports.first;
-  fprintf (stream, "%s\n", "#! .");
   for (; list; list = list->next)
-    fprintf (stream, "%s\n", list->name);
+    {
+      fputs (list->name, stream);
+      putc ('\n', stream);
+    }
 }
 #endif
 \f
@@ -2164,12 +2087,13 @@ write_import_file (stream)
 
 static void
 scan_prog_file (prog_name, which_pass)
-     char *prog_name;
+     const char *prog_name;
      enum pass which_pass;
 {
-  void (*int_handler) ();
-  void (*quit_handler) ();
-  char *nm_argv[4];
+  void (*int_handler) PARAMS ((int));
+  void (*quit_handler) PARAMS ((int));
+  char *real_nm_argv[4];
+  const char **nm_argv = (const char **) real_nm_argv;
   int pid;
   int argc = 0;
   int pipe_fd[2];
@@ -2200,8 +2124,8 @@ scan_prog_file (prog_name, which_pass)
   /* Trace if needed.  */
   if (vflag)
     {
-      char **p_argv;
-      char *str;
+      const char **p_argv;
+      const char *str;
 
       for (p_argv = &nm_argv[0]; (str = *p_argv) != (char *) 0; p_argv++)
        fprintf (stderr, " %s", str);
@@ -2215,38 +2139,32 @@ scan_prog_file (prog_name, which_pass)
   /* Spawn child nm on pipe */
   pid = vfork ();
   if (pid == -1)
-    {
-#ifdef vfork
-      fatal_perror ("fork");
-#else
-      fatal_perror ("vfork");
-#endif
-    }
+    fatal_perror (VFORK_STRING);
 
   if (pid == 0)                        /* child context */
     {
       /* setup stdout */
       if (dup2 (pipe_fd[1], 1) < 0)
-       fatal_perror ("dup2 (%d, 1)", pipe_fd[1]);
+       fatal_perror ("dup2 %d 1", pipe_fd[1]);
 
       if (close (pipe_fd[0]) < 0)
-       fatal_perror ("close (%d)", pipe_fd[0]);
+       fatal_perror ("close %d", pipe_fd[0]);
 
       if (close (pipe_fd[1]) < 0)
-       fatal_perror ("close (%d)", pipe_fd[1]);
+       fatal_perror ("close %d", pipe_fd[1]);
 
-      execv (nm_file_name, nm_argv);
-      fatal_perror ("executing %s", nm_file_name);
+      execv (nm_file_name, real_nm_argv);
+      fatal_perror ("execvp %s", nm_file_name);
     }
 
   /* Parent context from here on.  */
-  int_handler  = (void (*) ())signal (SIGINT,  SIG_IGN);
+  int_handler  = (void (*) PARAMS ((int))) signal (SIGINT,  SIG_IGN);
 #ifdef SIGQUIT
-  quit_handler = (void (*) ())signal (SIGQUIT, SIG_IGN);
+  quit_handler = (void (*) PARAMS ((int))) signal (SIGQUIT, SIG_IGN);
 #endif
 
   if (close (pipe_fd[1]) < 0)
-    fatal_perror ("close (%d)", pipe_fd[1]);
+    fatal_perror ("close %d", pipe_fd[1]);
 
   if (debug)
     fprintf (stderr, "\nnm output with constructors/destructors.\n");
@@ -2270,7 +2188,7 @@ scan_prog_file (prog_name, which_pass)
       name = p;
       /* Find the end of the symbol name.
         Do not include `|', because Encore nm can tack that on the end.  */
-      for (end = p; (ch2 = *end) != '\0' && !isspace (ch2) && ch2 != '|';
+      for (end = p; (ch2 = *end) != '\0' && !ISSPACE (ch2) && ch2 != '|';
           end++)
        continue;
 
@@ -2307,6 +2225,7 @@ scan_prog_file (prog_name, which_pass)
        case 5:
          if (which_pass != PASS_LIB)
            add_to_list (&frame_tables, name);
+         break;
 
        default:                /* not a constructor or destructor */
          continue;
@@ -2320,7 +2239,7 @@ scan_prog_file (prog_name, which_pass)
     fprintf (stderr, "\n");
 
   if (fclose (inf) != 0)
-    fatal_perror ("fclose of pipe");
+    fatal_perror ("fclose");
 
   do_wait (nm_file_name);
 
@@ -2356,9 +2275,11 @@ struct head libraries;
 
 /* Map the file indicated by NAME into memory and store its address.  */
 
+static void mapfile                    PARAMS ((const char *));
+
 static void
 mapfile (name)
-     char *name;
+     const char *name;
 {
   int fp;
   struct stat s;
@@ -2370,7 +2291,7 @@ mapfile (name)
   objsize = s.st_size;
   object = (unsigned) mmap (0, objsize, PROT_READ|PROT_WRITE, MAP_PRIVATE,
                            fp, 0);
-  if (object == -1)
+  if (object == (unsigned)-1)
     fatal ("unable to mmap file '%s'", name);
 
   close (fp);
@@ -2378,7 +2299,9 @@ mapfile (name)
 
 /* Helpers for locatelib.  */
 
-static char *libname;
+static const char *libname;
+
+static int libselect                   PARAMS ((struct direct *));
 
 static int
 libselect (d)
@@ -2394,6 +2317,7 @@ libselect (d)
    We must verify that the extension is numeric, because Sun saves the
    original versions of patched libraries with a .FCS extension.  Files with
    invalid extensions must go last in the sort, so that they will not be used.  */
+static int libcompare          PARAMS ((struct direct **, struct direct **));
 
 static int
 libcompare (d1, d2)
@@ -2404,7 +2328,7 @@ libcompare (d1, d2)
   char *e2 = (*d2)->d_name + i2;
 
   while (*e1 && *e2 && *e1 == '.' && *e2 == '.'
-        && e1[1] && isdigit (e1[1]) && e2[1] && isdigit (e2[1]))
+        && e1[1] && ISDIGIT (e1[1]) && e2[1] && ISDIGIT (e2[1]))
     {
       ++e1;
       ++e2;
@@ -2417,7 +2341,7 @@ libcompare (d1, d2)
   if (*e1)
     {
       /* It has a valid numeric extension, prefer this one.  */
-      if (*e1 == '.' && e1[1] && isdigit (e1[1]))
+      if (*e1 == '.' && e1[1] && ISDIGIT (e1[1]))
        return 1;
       /* It has a invalid numeric extension, must prefer the other one.  */
       else
@@ -2426,7 +2350,7 @@ libcompare (d1, d2)
   else if (*e2)
     {
       /* It has a valid numeric extension, prefer this one.  */
-      if (*e2 == '.' && e2[1] && isdigit (e2[1]))
+      if (*e2 == '.' && e2[1] && ISDIGIT (e2[1]))
        return -1;
       /* It has a invalid numeric extension, must prefer the other one.  */
       else
@@ -2438,16 +2362,17 @@ libcompare (d1, d2)
 
 /* Given the name NAME of a dynamic dependency, find its pathname and add
    it to the list of libraries.  */
+static void locatelib                  PARAMS ((const char *));
 
 static void
 locatelib (name)
-     char *name;
+     const char *name;
 {
-  static char **l;
+  static const char **l;
   static int cnt;
   char buf[MAXPATHLEN];
   char *p, *q;
-  char **pp;
+  const char **pp;
 
   if (l == 0)
     {
@@ -2463,8 +2388,7 @@ locatelib (name)
            if (*ld_rules == ':')
              cnt++;
          ld_rules = (char *) (ld_2->ld_rules + code);
-         ldr = (char *) malloc (strlen (ld_rules) + 1);
-         strcpy (ldr, ld_rules);
+         ldr = xstrdup (ld_rules);
        }
       p = getenv ("LD_LIBRARY_PATH");
       q = 0;
@@ -2474,10 +2398,9 @@ locatelib (name)
          for (q = p ; *q != 0; q++)
            if (*q == ':')
              cnt++;
-         q = (char *) malloc (strlen (p) + 1);
-         strcpy (q, p);
+         q = xstrdup (p);
        }
-      l = (char **) malloc ((cnt + 3) * sizeof (char *));
+      l = (const char **) xmalloc ((cnt + 3) * sizeof (char *));
       pp = l;
       if (ldr)
        {
@@ -2522,7 +2445,7 @@ locatelib (name)
   if (*pp == 0)
     {
       if (debug)
-       fprintf (stderr, "not found\n");
+       notice ("not found\n");
       else
        fatal ("dynamic dependency %s not found", name);
     }
@@ -2533,7 +2456,7 @@ locatelib (name)
 
 static void 
 scan_libraries (prog_name)
-     char *prog_name;
+     const char *prog_name;
 {
   struct exec *header;
   char *base;
@@ -2566,7 +2489,7 @@ scan_libraries (prog_name)
     }
 
   if (debug)
-    fprintf (stderr, "dynamic dependencies.\n");
+    notice ("dynamic dependencies.\n");
 
   ld_2 = (struct link_dynamic_2 *) ((long) ld->ld_un.ld_2 + (long)base);
   for (lo = (struct link_object *) ld_2->ld_need; lo;
@@ -2608,13 +2531,14 @@ scan_libraries (prog_name)
 
 static void 
 scan_libraries (prog_name)
-     char *prog_name;
+     const char *prog_name;
 {
   static struct head libraries;                /* list of shared libraries found */
   struct id *list;
-  void (*int_handler) ();
-  void (*quit_handler) ();
-  char *ldd_argv[4];
+  void (*int_handler) PARAMS ((int));
+  void (*quit_handler) PARAMS ((int));
+  char *real_ldd_argv[4];
+  const char **ldd_argv = (const char **) real_ldd_argv;
   int pid;
   int argc = 0;
   int pipe_fd[2];
@@ -2642,8 +2566,8 @@ scan_libraries (prog_name)
   /* Trace if needed.  */
   if (vflag)
     {
-      char **p_argv;
-      char *str;
+      const char **p_argv;
+      const char *str;
 
       for (p_argv = &ldd_argv[0]; (str = *p_argv) != (char *) 0; p_argv++)
        fprintf (stderr, " %s", str);
@@ -2657,46 +2581,40 @@ scan_libraries (prog_name)
   /* Spawn child ldd on pipe */
   pid = vfork ();
   if (pid == -1)
-    {
-#ifdef vfork
-      fatal_perror ("fork");
-#else
-      fatal_perror ("vfork");
-#endif
-    }
+    fatal_perror (VFORK_STRING);
 
   if (pid == 0)                        /* child context */
     {
       /* setup stdout */
       if (dup2 (pipe_fd[1], 1) < 0)
-       fatal_perror ("dup2 (%d, 1)", pipe_fd[1]);
+       fatal_perror ("dup2 %d 1", pipe_fd[1]);
 
       if (close (pipe_fd[0]) < 0)
-       fatal_perror ("close (%d)", pipe_fd[0]);
+       fatal_perror ("close %d", pipe_fd[0]);
 
       if (close (pipe_fd[1]) < 0)
-       fatal_perror ("close (%d)", pipe_fd[1]);
+       fatal_perror ("close %d", pipe_fd[1]);
 
-      execv (ldd_file_name, ldd_argv);
-      fatal_perror ("executing %s", ldd_file_name);
+      execv (ldd_file_name, real_ldd_argv);
+      fatal_perror ("execv %s", ldd_file_name);
     }
 
   /* Parent context from here on.  */
-  int_handler  = (void (*) ()) signal (SIGINT,  SIG_IGN);
+  int_handler  = (void (*) PARAMS ((int))) signal (SIGINT,  SIG_IGN);
 #ifdef SIGQUIT
-  quit_handler = (void (*) ()) signal (SIGQUIT, SIG_IGN);
+  quit_handler = (void (*) PARAMS ((int))) signal (SIGQUIT, SIG_IGN);
 #endif
 
   if (close (pipe_fd[1]) < 0)
-    fatal_perror ("close (%d)", pipe_fd[1]);
+    fatal_perror ("close %d", pipe_fd[1]);
 
   if (debug)
-    fprintf (stderr, "\nldd output with constructors/destructors.\n");
+    notice ("\nldd output with constructors/destructors.\n");
 
   /* Read each line of ldd output.  */
   while (fgets (buf, sizeof buf, inf) != (char *) 0)
     {
-      int ch, ch2;
+      int ch2;
       char *name, *end, *p = buf;
 
       /* Extract names of libraries and add to list.  */
@@ -2710,7 +2628,7 @@ scan_libraries (prog_name)
 
       /* Find the end of the symbol name.  */
       for (end = p; 
-          (ch2 = *end) != '\0' && ch2 != '\n' && !isspace (ch2) && ch2 != '|';
+          (ch2 = *end) != '\0' && ch2 != '\n' && !ISSPACE (ch2) && ch2 != '|';
           end++)
        continue;
       *end = '\0';
@@ -2727,7 +2645,7 @@ scan_libraries (prog_name)
     fprintf (stderr, "\n");
 
   if (fclose (inf) != 0)
-    fatal_perror ("fclose of pipe");
+    fatal_perror ("fclose");
 
   do_wait (ldd_file_name);
 
@@ -2755,25 +2673,40 @@ scan_libraries (prog_name)
 #ifdef OBJECT_FORMAT_COFF
 
 #if defined(EXTENDED_COFF)
+
 #   define GCC_SYMBOLS(X)      (SYMHEADER(X).isymMax + SYMHEADER(X).iextMax)
 #   define GCC_SYMENT          SYMR
-#   define GCC_OK_SYMBOL(X)    ((X).st == stProc && (X).sc == scText)
+#   define GCC_OK_SYMBOL(X)    ((X).st == stProc || (X).st == stGlobal)
 #   define GCC_SYMINC(X)       (1)
 #   define GCC_SYMZERO(X)      (SYMHEADER(X).isymMax)
 #   define GCC_CHECK_HDR(X)    (PSYMTAB(X) != 0)
+
 #else
+
 #   define GCC_SYMBOLS(X)      (HEADER(ldptr).f_nsyms)
 #   define GCC_SYMENT          SYMENT
 #   define GCC_OK_SYMBOL(X) \
      (((X).n_sclass == C_EXT) && \
       ((X).n_scnum > N_UNDEF) && \
-      (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) || \
-       ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT)))
+      (aix64_flag \
+       || (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) \
+           || ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT))))
 #   define GCC_UNDEF_SYMBOL(X) \
      (((X).n_sclass == C_EXT) && ((X).n_scnum == N_UNDEF))
 #   define GCC_SYMINC(X)       ((X).n_numaux+1)
 #   define GCC_SYMZERO(X)      0
-#   define GCC_CHECK_HDR(X)    (1)
+
+/* 0757 = U803XTOCMAGIC (AIX 4.3) and 0767 = U64_TOCMAGIC (AIX V5) */
+#ifdef _AIX51
+#   define GCC_CHECK_HDR(X) \
+     ((HEADER (X).f_magic == U802TOCMAGIC && ! aix64_flag) \
+      || (HEADER (X).f_magic == 0767 && aix64_flag))
+#else
+#   define GCC_CHECK_HDR(X) \
+     ((HEADER (X).f_magic == U802TOCMAGIC && ! aix64_flag) \
+      || (HEADER (X).f_magic == 0757 && aix64_flag))
+#endif
+
 #endif
 
 extern char *ldgetname ();
@@ -2789,16 +2722,12 @@ extern char *ldgetname ();
 
 static void
 scan_prog_file (prog_name, which_pass)
-     char *prog_name;
+     const char *prog_name;
      enum pass which_pass;
 {
   LDFILE *ldptr = NULL;
   int sym_index, sym_count;
   int is_shared = 0;
-#ifdef COLLECT_EXPORT_LIST
-  /* Should we generate an import list for given prog_name?  */
-  int import_flag = (which_pass == PASS_OBJ ? 0 : use_import_list (prog_name));
-#endif
 
   if (which_pass != PASS_FIRST && which_pass != PASS_OBJ)
     return;
@@ -2814,20 +2743,25 @@ scan_prog_file (prog_name, which_pass)
   do
     {
 #endif
-      if ((ldptr = ldopen (prog_name, ldptr)) != NULL)
+      /* Some platforms (e.g. OSF4) declare ldopen as taking a
+         non-const char * filename parameter, even though it will not
+         modify that string.  So we must cast away const-ness here,
+         which will cause -Wcast-qual to burp.  */
+      if ((ldptr = ldopen ((char *)prog_name, ldptr)) != NULL)
        {
-
-         if (!MY_ISCOFF (HEADER (ldptr).f_magic))
+         if (! MY_ISCOFF (HEADER (ldptr).f_magic))
            fatal ("%s: not a COFF file", prog_name);
 
-#ifdef COLLECT_EXPORT_LIST
-         /* Is current archive member a shared object?  */
-         is_shared = HEADER (ldptr).f_flags & F_SHROBJ;
-#endif
          if (GCC_CHECK_HDR (ldptr))
            {
              sym_count = GCC_SYMBOLS (ldptr);
              sym_index = GCC_SYMZERO (ldptr);
+
+#ifdef COLLECT_EXPORT_LIST
+             /* Is current archive member a shared object?  */
+             is_shared = HEADER (ldptr).f_flags & F_SHROBJ;
+#endif
+
              while (sym_index < sym_count)
                {
                  GCC_SYMENT symbol;
@@ -2853,96 +2787,85 @@ scan_prog_file (prog_name, which_pass)
                      switch (is_ctor_dtor (name))
                        {
                        case 1:
-                         if (! is_shared) add_to_list (&constructors, name);
+                         if (! is_shared)
+                           add_to_list (&constructors, name);
+#ifdef COLLECT_EXPORT_LIST
                          if (which_pass == PASS_OBJ)
                            add_to_list (&exports, name);
-#ifdef COLLECT_EXPORT_LIST
-                         /* If this symbol was undefined and we are building
-                            an import list, we should add a symbol to this
-                            list.  */
-                         else
-                           if (import_flag
-                               && is_in_list (name, undefined.first))
-                             add_to_list (&imports, name);
 #endif
                          break;
 
                        case 2:
-                         if (! is_shared) add_to_list (&destructors, name);
+                         if (! is_shared)
+                           add_to_list (&destructors, name);
+#ifdef COLLECT_EXPORT_LIST
                          if (which_pass == PASS_OBJ)
                            add_to_list (&exports, name);
-#ifdef COLLECT_EXPORT_LIST
-                         /* If this symbol was undefined and we are building
-                            an import list, we should add a symbol to this
-                            list.  */
-                         else
-                           if (import_flag
-                               && is_in_list (name, undefined.first))
-                             add_to_list (&imports, name);
 #endif
                          break;
 
 #ifdef COLLECT_EXPORT_LIST
                        case 3:
+#ifndef LD_INIT_SWITCH
                          if (is_shared)
                            add_to_list (&constructors, name);
+#endif
                          break;
 
                        case 4:
+#ifndef LD_INIT_SWITCH
                          if (is_shared)
                            add_to_list (&destructors, name);
+#endif
                          break;
 #endif
 
+                       case 5:
+                         if (! is_shared)
+                           add_to_list (&frame_tables, name);
+#ifdef COLLECT_EXPORT_LIST
+                         if (which_pass == PASS_OBJ)
+                           add_to_list (&exports, name);
+#endif
+                         break;
+
                        default:        /* not a constructor or destructor */
 #ifdef COLLECT_EXPORT_LIST
                          /* If we are building a shared object on AIX we need
-                            to explicitly export all global symbols or add
-                            them to import list.  */
+                            to explicitly export all global symbols.  */
                          if (shared_obj) 
-                           if (which_pass == PASS_OBJ && (! export_flag))
-                             add_to_list (&exports, name);
-                           else if (! is_shared && which_pass == PASS_FIRST
-                                    && import_flag
-                                    && is_in_list(name, undefined.first))
-                             add_to_list (&imports, name);
+                           {
+                             if (which_pass == PASS_OBJ && (! export_flag))
+                               add_to_list (&exports, name);
+                           }
 #endif
                          continue;
                        }
 
-#if !defined(EXTENDED_COFF)
                      if (debug)
+#if !defined(EXTENDED_COFF)
                        fprintf (stderr, "\tsec=%d class=%d type=%s%o %s\n",
                                 symbol.n_scnum, symbol.n_sclass,
                                 (symbol.n_type ? "0" : ""), symbol.n_type,
                                 name);
 #else
-                     if (debug)
                        fprintf (stderr,
-                                "\tiss = %5d, value = %5d, index = %5d, name = %s\n",
-                                symbol.iss, symbol.value, symbol.index, name);
+                                "\tiss = %5d, value = %5ld, index = %5d, name = %s\n",
+                                symbol.iss, (long) symbol.value, symbol.index, name);
 #endif
                    }
-#ifdef COLLECT_EXPORT_LIST
-                 /* If we are building a shared object we should collect
-                    information about undefined symbols for later
-                    import list generation.  */
-                 else if (shared_obj && GCC_UNDEF_SYMBOL (symbol))
-                   {
-                     char *name;
-
-                     if ((name = ldgetname (ldptr, &symbol)) == NULL)
-                       continue;               /* should never happen */
-
-                     /* All AIX function names have a duplicate entry
-                        beginning with a dot.  */
-                     if (*name == '.')
-                       ++name;
-                     add_to_list (&undefined, name);
-                   }
-#endif
                }
            }
+#ifdef COLLECT_EXPORT_LIST
+         else
+           {
+             /* If archive contains both 32-bit and 64-bit objects,
+                we want to skip objects in other mode so mismatch normal.  */
+             if (debug)
+               fprintf (stderr, "%s : magic=%o aix64=%d mismatch\n",
+                        prog_name, HEADER (ldptr).f_magic, aix64_flag);
+           }
+#endif
        }
       else
        {
@@ -2960,30 +2883,11 @@ scan_prog_file (prog_name, which_pass)
 
 
 #ifdef COLLECT_EXPORT_LIST
-
-/* This new function is used to decide whether we should
-   generate import list for an object or to use it directly.  */
-static int
-use_import_list (prog_name)
-     char *prog_name;
-{
-  char *p;
-
-  /* If we do not build a shared object then import list should not be used.  */
-  if (! shared_obj) return 0;
-
-  /* Currently we check only for libgcc, but this can be changed in future.  */
-  p = strstr (prog_name, "libgcc.a");
-  if (p != 0 && (strlen (p) == sizeof ("libgcc.a") - 1))
-    return 1;
-  return 0;
-}
-
 /* Given a library name without "lib" prefix, this function
    returns a full library name including a path.  */
 static char *
 resolve_lib_name (name)
-     char *name;
+     const char *name;
 {
   char *lib_buf;
   int i, j, l = 0;
@@ -2999,14 +2903,14 @@ resolve_lib_name (name)
       struct prefix_list *list = libpaths[i]->plist;
       for (; list; list = list->next)
        {
+         /* The following lines are needed because path_prefix list
+            may contain directories both with trailing '/' and
+            without it.  */
+         const char *p = "";
+         if (list->prefix[strlen(list->prefix)-1] != '/')
+           p = "/";
          for (j = 0; libexts[j]; j++)
            {
-              /* The following lines are needed because path_prefix list
-                 may contain directories both with trailing '/' and
-                 without it.  */
-              char *p = "";
-              if (list->prefix[strlen(list->prefix)-1] != '/')
-                p = "/";
                      sprintf (lib_buf, "%s%slib%s.%s",
                       list->prefix, p, name, libexts[j]);
 if (debug) fprintf (stderr, "searching for: %s\n", lib_buf);
@@ -3027,15 +2931,21 @@ if (debug) fprintf (stderr, "found: %s\n", lib_buf);
 
 /* Array of standard AIX libraries which should not
    be scanned for ctors/dtors.  */
-static char* aix_std_libs[] = {
+static const char *aix_std_libs[] = {
   "/unix",
   "/lib/libc.a",
+  "/lib/libm.a",
   "/lib/libc_r.a",
+  "/lib/libm_r.a",
   "/usr/lib/libc.a",
+  "/usr/lib/libm.a",
   "/usr/lib/libc_r.a",
+  "/usr/lib/libm_r.a",
   "/usr/lib/threads/libc.a",
   "/usr/ccs/lib/libc.a",
+  "/usr/ccs/lib/libm.a",
   "/usr/ccs/lib/libc_r.a",
+  "/usr/ccs/lib/libm_r.a",
   NULL
 };
 
@@ -3043,14 +2953,13 @@ static char* aix_std_libs[] = {
    if this name matches the location of a standard AIX library. */
 static int
 ignore_library (name)
-     char *name;
+     const char *name;
 {
-  char **p = &aix_std_libs[0];
+  const char **p = &aix_std_libs[0];
   while (*p++ != NULL)
     if (! strcmp (name, *p)) return 1;
   return 0;
 }
-
 #endif
 
 #endif /* OBJECT_FORMAT_COFF */
@@ -3103,13 +3012,13 @@ struct file_info
 extern int decode_mach_o_hdr ();
 extern int encode_mach_o_hdr ();
 
-static void add_func_table     PROTO((mo_header_t *, load_all_t *,
+static void add_func_table     PARAMS ((mo_header_t *, load_all_t *,
                                       symbol_info_t *, int));
-static void print_header       PROTO((mo_header_t *));
-static void print_load_command PROTO((load_union_t *, size_t, int));
-static void bad_header         PROTO((int));
-static struct file_info        *read_file  PROTO((char *, int, int));
-static void end_file           PROTO((struct file_info *));
+static void print_header       PARAMS ((mo_header_t *));
+static void print_load_command PARAMS ((load_union_t *, size_t, int));
+static void bad_header         PARAMS ((int));
+static struct file_info        *read_file  PARAMS ((const char *, int, int));
+static void end_file           PARAMS ((struct file_info *));
 \f
 /* OSF/rose specific version to scan the name list of the loaded
    program for the symbols g++ uses for static constructors and
@@ -3123,7 +3032,7 @@ static void end_file              PROTO((struct file_info *));
 
 static void
 scan_prog_file (prog_name, which_pass)
-     char *prog_name;
+     const char *prog_name;
      enum pass which_pass;
 {
   char *obj;
@@ -3145,7 +3054,7 @@ scan_prog_file (prog_name, which_pass)
 
   prog_fd = open (prog_name, (rw) ? O_RDWR : O_RDONLY);
   if (prog_fd < 0)
-    fatal_perror ("cannot read %s", prog_name);
+    fatal_perror ("open %s", prog_name);
 
   obj_file = read_file (prog_name, prog_fd, rw);
   obj = obj_file->start;
@@ -3191,7 +3100,7 @@ scan_prog_file (prog_name, which_pass)
       if (rw)
        {
          load_union_t *ptr = (load_union_t *) xmalloc (load_hdr->hdr.ldci_cmd_size);
-         bcopy ((char *)load_hdr, (char *)ptr, load_hdr->hdr.ldci_cmd_size);
+         memcpy ((char *)ptr, (char *)load_hdr, load_hdr->hdr.ldci_cmd_size);
          load_hdr = ptr;
 
          /* null out old command map, because we will rewrite at the end.  */
@@ -3232,7 +3141,7 @@ scan_prog_file (prog_name, which_pass)
 
          if (debug)
            {
-             char *kind = "unknown";
+             const char *kind = "unknown";
 
              switch (load_hdr->sym.symc_kind)
                {
@@ -3241,8 +3150,8 @@ scan_prog_file (prog_name, which_pass)
                case SYMC_STABS:           kind = "stabs";   break;
                }
 
-             fprintf (stderr, "\nProcessing symbol table #%d, offset = 0x%.8lx, kind = %s\n",
-                      symbol_load_cmds, load_hdr->hdr.ldci_section_off, kind);
+             notice ("\nProcessing symbol table #%d, offset = 0x%.8lx, kind = %s\n",
+                     symbol_load_cmds, load_hdr->hdr.ldci_section_off, kind);
            }
 
          if (load_hdr->sym.symc_kind != SYMC_DEFINED_SYMBOLS)
@@ -3326,15 +3235,15 @@ scan_prog_file (prog_name, which_pass)
        add_func_table (&hdr, load_array, main_sym, FNTC_INITIALIZATION);
 
       if (debug)
-       fprintf (stderr, "\nUpdating header and load commands.\n\n");
+       notice ("\nUpdating header and load commands.\n\n");
 
       hdr.moh_n_load_cmds++;
       size = sizeof (load_cmd_map_command_t) + (sizeof (mo_offset_t) * (hdr.moh_n_load_cmds - 1));
 
       /* Create new load command map.  */
       if (debug)
-       fprintf (stderr, "load command map, %d cmds, new size %ld.\n",
-                (int)hdr.moh_n_load_cmds, (long)size);
+       notice ("load command map, %d cmds, new size %ld.\n",
+               (int) hdr.moh_n_load_cmds, (long) size);
 
       load_map = (load_union_t *) xcalloc (1, size);
       load_map->map.ldc_header.ldci_cmd_type = LDC_CMD_MAP;
@@ -3364,7 +3273,7 @@ scan_prog_file (prog_name, which_pass)
        bad_header (status);
 
       if (debug)
-       fprintf (stderr, "writing load commands.\n\n");
+       notice ("writing load commands.\n\n");
 
       /* Write load commands */
       offset = hdr.moh_first_cmd_off;
@@ -3384,7 +3293,7 @@ scan_prog_file (prog_name, which_pass)
   end_file (obj_file);
 
   if (close (prog_fd))
-    fatal_perror ("closing %s", prog_name);
+    fatal_perror ("close %s", prog_name);
 
   if (debug)
     fprintf (stderr, "\n");
@@ -3462,12 +3371,11 @@ add_func_table (hdr_p, load_array, sym, type)
     }
 
   if (debug)
-    fprintf (stderr,
-            "%s function, region %d, offset = %ld (0x%.8lx)\n",
-            (type == FNTC_INITIALIZATION) ? "init" : "term",
-            (int)ptr->func.fntc_entry_loc[i].adr_lcid,
-            (long)ptr->func.fntc_entry_loc[i].adr_sctoff,
-            (long)ptr->func.fntc_entry_loc[i].adr_sctoff);
+    notice ("%s function, region %d, offset = %ld (0x%.8lx)\n",
+           type == FNTC_INITIALIZATION ? "init" : "term",
+           (int) ptr->func.fntc_entry_loc[i].adr_lcid,
+           (long) ptr->func.fntc_entry_loc[i].adr_sctoff,
+           (long) ptr->func.fntc_entry_loc[i].adr_sctoff);
 
 }
 
@@ -3524,7 +3432,7 @@ print_load_command (load_hdr, offset, number)
      int number;
 {
   mo_long_t type = load_hdr->hdr.ldci_cmd_type;
-  char *type_str = (char *) 0;
+  const char *type_str = (char *) 0;
 
   switch (type)
     {
@@ -3557,7 +3465,7 @@ print_load_command (load_hdr, offset, number)
 
   else
     {
-      char *region = "";
+      const char *region = "";
       switch (load_hdr->region.regc_usage_type)
        {
        case REG_TEXT_T:        region = ", .text";     break;
@@ -3588,22 +3496,17 @@ static void
 bad_header (status)
      int status;
 {
-  char *msg = (char *) 0;
-
   switch (status)
     {
-    case MO_ERROR_BAD_MAGIC:           msg = "bad magic number";               break;
-    case MO_ERROR_BAD_HDR_VERS:                msg = "bad header version";             break;
-    case MO_ERROR_BAD_RAW_HDR_VERS:    msg = "bad raw header version";         break;
-    case MO_ERROR_BUF2SML:             msg = "raw header buffer too small";    break;
-    case MO_ERROR_OLD_RAW_HDR_FILE:    msg = "old raw header file";            break;
-    case MO_ERROR_UNSUPPORTED_VERS:    msg = "unsupported version";            break;
+    case MO_ERROR_BAD_MAGIC:           fatal ("bad magic number");
+    case MO_ERROR_BAD_HDR_VERS:                fatal ("bad header version");
+    case MO_ERROR_BAD_RAW_HDR_VERS:    fatal ("bad raw header version");
+    case MO_ERROR_BUF2SML:             fatal ("raw header buffer too small");
+    case MO_ERROR_OLD_RAW_HDR_FILE:    fatal ("old raw header file");
+    case MO_ERROR_UNSUPPORTED_VERS:    fatal ("unsupported version");
+    default:
+      fatal ("unknown {de,en}code_mach_o_hdr return value %d", status);
     }
-
-  if (msg == (char *) 0)
-    fatal ("unknown {de,en}code_mach_o_hdr return value %d", status);
-  else
-    fatal ("%s", msg);
 }
 
 \f
@@ -3611,7 +3514,7 @@ bad_header (status)
 
 static struct file_info *
 read_file (name, fd, rw)
-     char *name;               /* filename */
+     const char *name;         /* filename */
      int fd;                   /* file descriptor */
      int rw;                   /* read/write */
 {
@@ -3659,7 +3562,7 @@ read_file (name, fd, rw)
       p->use_mmap = 0;
       p->start = xmalloc (p->size);
       if (lseek (fd, 0L, SEEK_SET) < 0)
-       fatal_perror ("lseek to 0 on %s", name);
+       fatal_perror ("lseek %s 0", name);
 
       len = read (fd, p->start, p->size);
       if (len < 0)
@@ -3707,7 +3610,7 @@ end_file (ptr)
            fprintf (stderr, "write %s\n", ptr->name);
 
          if (lseek (ptr->fd, 0L, SEEK_SET) < 0)
-           fatal_perror ("lseek to 0 on %s", ptr->name);
+           fatal_perror ("lseek %s 0", ptr->name);
 
          len = write (ptr->fd, ptr->start, ptr->size);
          if (len < 0)