OSDN Git Service

91th Cygnus<->FSF merge
[pf3gnuchains/gcc-fork.git] / gcc / collect2.c
index bc4e93e..e5f404f 100644 (file)
@@ -1,8 +1,6 @@
-/* Collect static initialization info into data structures
-   that can be traversed by C++ initialization and finalization
-   routines.
-
-   Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+/* Collect static initialization info into data structures that can be
+   traversed by C++ initialization and finalization routines.
+   Copyright (C) 1992, 93, 94, 95, 96, 1997 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).
@@ -25,7 +23,7 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
 
 
-/* Build tables of static constructors and destructors and run ld. */
+/* Build tables of static constructors and destructors and run ld.  */
 
 #include "config.h"
 #include <sys/types.h>
@@ -35,14 +33,12 @@ Boston, MA 02111-1307, USA.  */
 #include <signal.h>
 #include <sys/file.h>
 #include <sys/stat.h>
-#ifdef NO_WAIT_H
-#include <sys/wait.h>
-#endif
 
 #define COLLECT
 
 #include "demangle.h"
 #include "obstack.h"
+#include "gansidecl.h"
 
 #ifndef errno
 extern int errno;
@@ -63,23 +59,10 @@ char *strerror();
 #define obstack_chunk_alloc xmalloc
 #define obstack_chunk_free free
 
-#if !defined (__STDC__) && !defined (const)
-#define const
-#endif
-
 #ifdef USG
 #define vfork fork
 #endif
 
-/* Add prototype support.  */
-#ifndef PROTO
-#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
-#define PROTO(ARGS) ARGS
-#else
-#define PROTO(ARGS) ()
-#endif
-#endif
-
 #ifndef R_OK
 #define R_OK 4
 #define W_OK 2
@@ -99,13 +82,7 @@ char *strerror();
 #define WEXITSTATUS(S) (((S) & 0xff00) >> 8)
 #endif
 
-/* On MSDOS, write temp files in current dir
-   because there's no place else we can expect to use.  */
-#ifdef __MSDOS__
-#ifndef P_tmpdir
-#define P_tmpdir "./"
-#endif
-#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
@@ -158,6 +135,10 @@ char *strerror();
 #define MY_ISCOFF(X) ISCOFF (X)
 #endif
 
+#ifdef XCOFF_DEBUGGING_INFO
+#define XCOFF_SCAN_LIBS
+#endif
+
 #endif /* OBJECT_FORMAT_COFF */
 
 #ifdef OBJECT_FORMAT_ROSE
@@ -196,7 +177,7 @@ char *strerror();
 #define SYMBOL__MAIN __main
 #endif
 
-#if defined (LDD_SUFFIX) || SUNOS4_SHARED_LIBRARIES
+#if defined (LDD_SUFFIX) || SUNOS4_SHARED_LIBRARIES || defined(XCOFF_SCAN_LIBS)
 #define SCAN_LIBRARIES
 #endif
 
@@ -206,7 +187,7 @@ int do_collecting = 1;
 int do_collecting = 0;
 #endif
 \f
-/* Linked lists of constructor and destructor names. */
+/* Linked lists of constructor and destructor names.  */
 
 struct id 
 {
@@ -248,10 +229,9 @@ 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 char *export_file;              /* <xxx>.x for AIX export list. */
-static int  auto_export = 1;           /* true if exporting everything. */
+static char *c_file;                   /* <xxx>.c for constructor/destructor list.  */
+static char *o_file;                   /* <xxx>.o for constructor/destructor list.  */
+static char *export_file;              /* <xxx>.x for AIX export list.  */
 char *ldout;                           /* File for ld errors.  */
 static char *output_file;              /* Output file for ld.  */
 static char *nm_file_name;             /* pathname of nm */
@@ -280,8 +260,8 @@ extern FILE *fdopen ();
 
 struct prefix_list
 {
-  char *prefix;               /* String to prepend to the path. */
-  struct prefix_list *next;   /* Next in linked list. */
+  char *prefix;               /* String to prepend to the path.  */
+  struct prefix_list *next;   /* Next in linked list.  */
 };
 
 struct path_prefix
@@ -296,7 +276,6 @@ 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 void choose_temp_base   PROTO((void));
 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 *));
@@ -392,7 +371,7 @@ collect_exit (status)
 }
 
 \f
-/* Die when sys call fails. */
+/* Die when sys call fails.  */
 
 void
 fatal_perror (string, arg1, arg2, arg3)
@@ -403,10 +382,10 @@ fatal_perror (string, arg1, arg2, arg3)
   fprintf (stderr, "collect2: ");
   fprintf (stderr, string, arg1, arg2, arg3);
   fprintf (stderr, ": %s\n", my_strerror (e));
-  collect_exit (1);
+  collect_exit (FATAL_EXIT_CODE);
 }
 
-/* Just die. */
+/* Just die.  */
 
 void
 fatal (string, arg1, arg2, arg3)
@@ -415,7 +394,7 @@ fatal (string, arg1, arg2, arg3)
   fprintf (stderr, "collect2: ");
   fprintf (stderr, string, arg1, arg2, arg3);
   fprintf (stderr, "\n");
-  collect_exit (1);
+  collect_exit (FATAL_EXIT_CODE);
 }
 
 /* Write error message.  */
@@ -452,6 +431,9 @@ handler (signo)
   if (ldout != 0 && ldout[0])
     maybe_unlink (ldout);
 
+  if (export_file != 0 && export_file[0])
+    maybe_unlink (export_file);
+
   signal (signo, SIG_DFL);
   kill (getpid (), signo);
 }
@@ -466,7 +448,7 @@ xcalloc (size1, size2)
     return ptr;
 
   fatal ("out of memory");
-  return (char *)0;
+  return (char *) 0;
 }
 
 char *
@@ -478,7 +460,7 @@ xmalloc (size)
     return ptr;
 
   fatal ("out of memory");
-  return (char *)0;
+  return (char *) 0;
 }
 
 char *
@@ -567,6 +549,7 @@ dump_file (name)
        break;
       putc (c, stderr);
     }
+  fclose (stream);
 }
 \f
 /* Decide whether the given symbol is:
@@ -625,42 +608,6 @@ is_ctor_dtor (s)
     }
   return 0;
 }
-
-\f
-/* Compute a string to use as the base of all temporary file names.
-   It is substituted for %g.  */
-
-static void
-choose_temp_base ()
-{
-  char *base = getenv ("TMPDIR");
-  int len;
-
-  if (base == (char *)0)
-    {
-#ifdef P_tmpdir
-      if (access (P_tmpdir, R_OK | W_OK) == 0)
-       base = P_tmpdir;
-#endif
-      if (base == (char *)0)
-       {
-         if (access ("/usr/tmp", R_OK | W_OK) == 0)
-           base = "/usr/tmp/";
-         else
-           base = "/tmp/";
-       }
-    }
-
-  len = strlen (base);
-  temp_filename = xmalloc (len + sizeof("/ccXXXXXX") + 1);
-  strcpy (temp_filename, base);
-  if (len > 0 && temp_filename[len-1] != '/')
-    temp_filename[len++] = '/';
-  strcpy (temp_filename + len, "ccXXXXXX");
-
-  mktemp (temp_filename);
-  temp_filename_length = strlen (temp_filename);
-}
 \f
 /* Routine to add variables to the environment.  */
 
@@ -772,7 +719,7 @@ is_in_prefix_list (pprefix, string, filep)
 /* Search for NAME using prefix list PPREFIX.  We only look for executable
    files. 
 
-   Return 0 if not found, otherwise return its name, allocated with malloc. */
+   Return 0 if not found, otherwise return its name, allocated with malloc.  */
 
 static char *
 find_a_file (pprefix, name)
@@ -909,7 +856,7 @@ prefix_from_string (p, pprefix)
     }
 }
 \f
-/* Main program. */
+/* Main program.  */
 
 int
 main (argc, argv)
@@ -955,7 +902,11 @@ main (argc, argv)
   vflag = 1;
 #endif
 
+#ifndef DEFAULT_A_OUT_NAME
   output_file = "a.out";
+#else
+  output_file = DEFAULT_A_OUT_NAME;
+#endif
 
   obstack_begin (&temporary_obstack, 0);
   obstack_begin (&permanent_obstack, 0);
@@ -1195,8 +1146,9 @@ main (argc, argv)
 
   *ld1++ = *ld2++ = ld_file_name;
 
-  /* Make temp file names. */
-  choose_temp_base ();
+  /* 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);
   export_file = xmalloc (temp_filename_length + sizeof (".x"));
@@ -1217,11 +1169,11 @@ main (argc, argv)
      If you propose to make GCC pass some other option,
      just imagine what will happen if ld is really ld!!!  */
 
-  /* Parse arguments.  Remember output file spec, pass the rest to ld. */
+  /* Parse arguments.  Remember output file spec, pass the rest to ld.  */
   /* After the first file, put in the c++ rt0.  */
 
   first_file = 1;
-  while ((arg = *++argv) != (char *)0)
+  while ((arg = *++argv) != (char *) 0)
     {
       *ld1++ = *ld2++ = arg;
 
@@ -1239,15 +1191,6 @@ main (argc, argv)
                }
              break;
 
-#ifdef COLLECT_EXPORT_LIST
-           case 'b':
-             if ((!strncmp (arg, "-bE:", 4)
-                  || !strncmp (arg, "-bexport:", 9))
-                 && strcmp (arg, "-bexport:/usr/lib/libg.exp"))
-               auto_export = 0;
-             break;
-#endif
-
            case 'l':
              if (first_file)
                {
@@ -1288,7 +1231,7 @@ main (argc, argv)
              break;
            }
        }
-      else if ((p = rindex (arg, '.')) != (char *)0
+      else if ((p = rindex (arg, '.')) != (char *) 0
               && (strcmp (p, ".o") == 0 || strcmp (p, ".a") == 0))
        {
          if (first_file)
@@ -1337,7 +1280,7 @@ main (argc, argv)
     *ld1++ = buf;
     *ld2++ = buf;
     exportf = fopen (export_file, "w");
-    if (exportf == (FILE *)0)
+    if (exportf == (FILE *) 0)
       fatal_perror ("%s", export_file);
     write_export_file (exportf);
     if (fclose (exportf))
@@ -1346,7 +1289,7 @@ main (argc, argv)
 #endif
 
   *c_ptr++ = c_file;
-  *object = *c_ptr = *ld1 = (char *)0;
+  *object = *c_ptr = *ld1 = (char *) 0;
 
   if (vflag)
     {
@@ -1408,13 +1351,13 @@ main (argc, argv)
   unlink (ldout);
 
   /* If -r or they'll be run via some other method, don't build the
-     constructor or destructor list, just return now. */
+     constructor or destructor list, just return now.  */
   if (rflag || ! do_collecting)
     return 0;
 
   /* 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. */
+     Write the constructor and destructor tables to a .s file and reload.  */
 
   scan_prog_file (output_file, PASS_FIRST);
 
@@ -1455,7 +1398,7 @@ main (argc, argv)
 
   maybe_unlink(output_file);
   outf = fopen (c_file, "w");
-  if (outf == (FILE *)0)
+  if (outf == (FILE *) 0)
     fatal_perror ("%s", c_file);
 
   write_c_file (outf, c_file);
@@ -1470,7 +1413,7 @@ main (argc, argv)
   *ld2++ = LD_FINI_SWITCH;
   *ld2++ = fininame;
 #endif
-  *ld2 = (char*)0;
+  *ld2 = (char*) 0;
 
 #ifdef COLLECT_EXPORT_LIST
   if (shared_obj)
@@ -1480,7 +1423,7 @@ main (argc, argv)
       add_to_list (&exports, "_GLOBAL__DI");
       add_to_list (&exports, "_GLOBAL__DD");
       exportf = fopen (export_file, "w");
-      if (exportf == (FILE *)0)
+      if (exportf == (FILE *) 0)
        fatal_perror ("%s", export_file);
       write_export_file (exportf);
       if (fclose (exportf))
@@ -1502,7 +1445,7 @@ main (argc, argv)
     }
 
   /* Assemble the constructor and destructor tables.
-     Link the tables in with the rest of the program. */
+     Link the tables in with the rest of the program.  */
 
   fork_execute ("gcc",  c_argv);
   fork_execute ("ld", ld2_argv);
@@ -1518,7 +1461,7 @@ main (argc, argv)
 }
 
 \f
-/* Wait for a process to finish, and exit if a non-zero status is found. */
+/* Wait for a process to finish, and exit if a non-zero status is found.  */
 
 int
 collect_wait (prog)
@@ -1545,7 +1488,7 @@ collect_wait (prog)
                 (status & 0200) ? ", core dumped" : "");
 #endif
 
-         collect_exit (127);
+         collect_exit (FATAL_EXIT_CODE);
        }
 
       if (WIFEXITED (status))
@@ -1587,7 +1530,7 @@ collect_execute (prog, argv, redir)
       else
        fprintf (stderr, "[cannot find %s]", prog);
 
-      for (p_argv = &argv[1]; (str = *p_argv) != (char *)0; p_argv++)
+      for (p_argv = &argv[1]; (str = *p_argv) != (char *) 0; p_argv++)
        fprintf (stderr, " %s", str);
 
       fprintf (stderr, "\n");
@@ -1812,7 +1755,7 @@ write_c_file_stat (stream, name)
     }
 }
 
-/* Write the constructor/destructor tables. */
+/* Write the constructor/destructor tables.  */
 
 static void
 write_c_file_glob (stream, name)
@@ -1846,12 +1789,14 @@ write_c_file (stream, name)
      FILE *stream;
      char *name;
 {
+  fprintf (stream, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n");
 #ifndef LD_INIT_SWITCH
   if (! shared_obj)
     write_c_file_glob (stream, name);
   else
 #endif
     write_c_file_stat (stream, name);
+  fprintf (stream, "#ifdef __cplusplus\n}\n#endif\n");
 }
 
 static void
@@ -1900,13 +1845,13 @@ scan_prog_file (prog_name, which_pass)
     nm_argv[argc++] = NM_FLAGS;
 
   nm_argv[argc++] = prog_name;
-  nm_argv[argc++] = (char *)0;
+  nm_argv[argc++] = (char *) 0;
 
   if (pipe (pipe_fd) < 0)
     fatal_perror ("pipe");
 
   inf = fdopen (pipe_fd[0], "r");
-  if (inf == (FILE *)0)
+  if (inf == (FILE *) 0)
     fatal_perror ("fdopen");
 
   /* Trace if needed.  */
@@ -1915,7 +1860,7 @@ scan_prog_file (prog_name, which_pass)
       char **p_argv;
       char *str;
 
-      for (p_argv = &nm_argv[0]; (str = *p_argv) != (char *)0; p_argv++)
+      for (p_argv = &nm_argv[0]; (str = *p_argv) != (char *) 0; p_argv++)
        fprintf (stderr, " %s", str);
 
       fprintf (stderr, "\n");
@@ -1964,13 +1909,13 @@ scan_prog_file (prog_name, which_pass)
     fprintf (stderr, "\nnm output with constructors/destructors.\n");
 
   /* Read each line of nm output.  */
-  while (fgets (buf, sizeof buf, inf) != (char *)0)
+  while (fgets (buf, sizeof buf, inf) != (char *) 0)
     {
       int ch, ch2;
       char *name, *end;
 
       /* If it contains a constructor or destructor name, add the name
-        to the appropriate list. */
+        to the appropriate list.  */
 
       for (p = buf; (ch = *p) != '\0' && ch != '\n' && ch != '_'; p++)
        if (ch == ' ' && p[1] == 'U' && p[2] == ' ')
@@ -2049,7 +1994,7 @@ scan_prog_file (prog_name, which_pass)
 #include <link.h>
 #include <sys/mman.h>
 #include <sys/param.h>
-#include <sys/unistd.h>
+#include <unistd.h>
 #include <sys/dir.h>
 
 /* pointers to the object file */
@@ -2095,7 +2040,7 @@ libselect (d)
   return (strncmp (libname, d->d_name, strlen (libname)) == 0);
 }
 
-/* If one file has an additional numeric extention past LIBNAME, then put
+/* If one file has an additional numeric extension past LIBNAME, then put
    that one first in the sort.  If both files have additional numeric
    extensions, then put the one with the higher number first in the sort.
 
@@ -2407,7 +2352,7 @@ scan_libraries (prog_name)
       int ch, ch2;
       char *name, *end, *p = buf;
 
-      /* Extract names of libraries and add to list. */
+      /* Extract names of libraries and add to list.  */
       PARSE_LDD_OUTPUT (p);
       if (p == 0)
        continue;
@@ -2416,7 +2361,7 @@ scan_libraries (prog_name)
       if (strncmp (name, "not found", sizeof ("not found") - 1) == 0)
        fatal ("dynamic dependency %s not found", buf);
 
-      /* Find the end of the symbol name. */
+      /* Find the end of the symbol name.  */
       for (end = p; 
           (ch2 = *end) != '\0' && ch2 != '\n' && !isspace (ch2) && ch2 != '|';
           end++)
@@ -2530,7 +2475,7 @@ scan_prog_file (prog_name, which_pass)
 
 #ifdef XCOFF_DEBUGGING_INFO
              /* All AIX function names have a duplicate entry beginning
-                with a dot. */
+                with a dot.  */
              if (*name == '.')
                ++name;
 #endif
@@ -2550,8 +2495,6 @@ scan_prog_file (prog_name, which_pass)
                  break;
 
                default:                /* not a constructor or destructor */
-                 if (which_pass == PASS_OBJ && auto_export)
-                   add_to_list (&exports, name);
                  continue;
                }
 
@@ -2573,6 +2516,175 @@ scan_prog_file (prog_name, which_pass)
   (void) ldclose(ldptr);
 }
 
+#ifdef XCOFF_SCAN_LIBS
+/* Scan imported AIX libraries for GCC static ctors and dtors.
+   FIXME: it is possible to link an executable without the actual import
+         library by using an "import file" - a text file listing symbols
+         exported by a library.  To support this, we would have to scan
+         import files as well as actual shared binaries to find GCC ctors.
+   TODO: use memory mapping instead of 'ld' routines, files are already
+        memory mapped, but we could eliminate the extra in-memory copies.
+        Is it worth the effort?  */
+
+static void
+scan_libraries (prog_name)
+     char *prog_name;
+{
+  LDFILE *ldptr;
+  SCNHDR ldsh;
+  static struct path_prefix libpath; /* we should only do this once */
+
+  if ((ldptr = ldopen (prog_name, ldptr)) == NULL)
+    fatal ("%s: can't open as COFF file", prog_name);
+      
+  if (!MY_ISCOFF (HEADER (ldptr).f_magic))
+    fatal ("%s: not a COFF file", prog_name);
+
+  /* find and read loader section */
+  if (ldnshread (ldptr, _LOADER, &ldsh))
+    {
+      LDHDR ldh;
+      char *impbuf;
+      int entry;
+
+      FSEEK (ldptr, ldsh.s_scnptr, BEGINNING);
+      FREAD (&ldh, sizeof (ldh), 1, ldptr);
+      /* read import library list */
+      impbuf = alloca (ldh.l_istlen);
+      FSEEK (ldptr, ldh.l_impoff + ldsh.s_scnptr, BEGINNING);
+      FREAD (impbuf, ldh.l_istlen, 1, ldptr);
+
+      if (debug)
+       fprintf (stderr, "LIBPATH=%s\n", impbuf);
+      prefix_from_string (impbuf, &libpath);
+
+      /* skip LIBPATH and empty base and member fields */
+      impbuf += strlen (impbuf) + 3;
+      for (entry = 1; entry < ldh.l_nimpid; ++entry)
+       {
+         char *impath = impbuf;
+         char *implib = impath + strlen (impath) + 1;
+         char *impmem = implib + strlen (implib) + 1;
+         char *soname = NULL;
+         char *trial;
+         int pathlen;
+         LDFILE *libptr = NULL;
+         struct prefix_list *pl;
+         ARCHDR ah;
+
+         impbuf = impmem + strlen (impmem) + 1;
+         if (debug)
+           fprintf (stderr, "PATH+BASE=%s%s\n", impath, implib);
+         /* Skip AIX kernel exports */
+         if (*impath == '/' && *(impath+1) == '\0'
+             && strcmp (implib, "unix") == 0)
+           continue;
+         pathlen = strlen (impath);
+          trial = alloca (MAX (pathlen + 1, libpath.max_len)
+                         + strlen (implib) + 1);
+         if (*impath)
+           {
+             strcpy (trial, impath);
+             if (impath[pathlen - 1] != '/')
+               trial[pathlen++] = '/';
+             strcpy (trial + pathlen, implib);
+             if (access (trial, R_OK) == 0)
+               soname = trial;
+           }
+         else
+           for (pl = libpath.plist; pl; pl = pl->next)
+             {
+               strcpy (trial, pl->prefix);
+               strcat (trial, implib);
+               if (access (trial, R_OK) == 0)
+                 {
+                   soname = trial;
+                   break;
+                 }
+             }
+
+         if (! soname)
+           fatal ("%s: library not found", implib);
+         if (debug)
+           if (*impmem)
+             fprintf (stderr, "%s (%s)\n", soname, impmem);
+           else
+             fprintf (stderr, "%s\n", soname);
+
+         do
+           {
+             /* scan imported shared objects for GCC GLOBAL ctors */
+             short type;
+             if ((libptr = ldopen (soname, libptr)) == NULL)
+               fatal ("%s: can't open import library", soname);
+             if (TYPE (libptr) == ARTYPE)
+               {
+                 LDFILE *memptr;
+                 if (! *impmem)
+                   fatal ("%s: no archive member specified", soname);
+                 ldahread (libptr, &ah);
+                 if (strcmp (ah.ar_name, impmem))
+                   continue;
+               }
+             type = HEADER (libptr).f_magic;
+             if (HEADER (libptr).f_flags & F_SHROBJ)
+               {
+                 SCNHDR soldsh;
+                 LDHDR soldh;
+                 long symcnt, i;
+                 char *ldstrings;
+                 LDSYM *lsyms;
+                 if (!ldnshread (libptr, _LOADER, &soldsh))
+                   fatal ("%s: not an import library", soname);
+                 FSEEK (libptr, soldsh.s_scnptr, BEGINNING);
+                 if (FREAD (&soldh, sizeof (soldh), 1, libptr) != 1)
+                   fatal ("%s: can't read loader section", soname);
+                 /*fprintf (stderr, "\tscanning %s\n", soname);*/
+                 symcnt = soldh.l_nsyms;
+                 lsyms = (LDSYM *) alloca (symcnt * sizeof (*lsyms));
+                 symcnt = FREAD (lsyms, sizeof (*lsyms), symcnt, libptr);
+                 ldstrings = alloca (soldh.l_stlen);
+                 FSEEK (libptr, soldsh.s_scnptr+soldh.l_stoff, BEGINNING);
+                 FREAD (ldstrings, soldh.l_stlen, 1, libptr);
+                 for (i = 0; i < symcnt; ++i)
+                   {
+                     LDSYM *l = lsyms + i;
+                     if (LDR_EXPORT (*l))
+                       {
+                         char *expname = 0;
+                         if (l->l_zeroes)
+                           expname = l->l_name;
+                         else if (l->l_offset < soldh.l_stlen)
+                           expname = ldstrings + l->l_offset;
+                         switch (is_ctor_dtor (expname))
+                           {
+                           case 3:
+                             if (debug)
+                               fprintf (stderr, "\t%s\n", expname);
+                             add_to_list (&constructors, expname);
+                             break;
+
+                           case 4:
+                             add_to_list (&destructors, expname);
+                             break;
+
+                           default: /* not a constructor or destructor */
+                             continue;
+                           }
+                       }
+                   }
+               }
+             else
+               fprintf (stderr, "%s: type = %04X flags = %04X\n", 
+                        ah.ar_name, type, HEADER (libptr).f_flags);
+           }
+         while (ldclose (libptr) == FAILURE);
+         /* printf (stderr, "closed %s\n", soname); */
+       }
+    }
+}
+#endif /* XCOFF_SCAN_LIBS */
+
 #endif /* OBJECT_FORMAT_COFF */
 
 \f
@@ -2626,7 +2738,7 @@ extern int encode_mach_o_hdr ();
 static void add_func_table     PROTO((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 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 *));
@@ -2769,10 +2881,10 @@ scan_prog_file (prog_name, which_pass)
            continue;
 
          str_sect = load_array[load_hdr->sym.symc_strings_section].section;
-         if (str_sect == (char *)0)
+         if (str_sect == (char *) 0)
            fatal ("string section missing");
 
-         if (load_cmd->section == (char *)0)
+         if (load_cmd->section == (char *) 0)
            fatal ("section pointer missing");
 
          num_syms = load_hdr->sym.symc_nentries;
@@ -2841,7 +2953,7 @@ scan_prog_file (prog_name, which_pass)
         do anything, since in the current version, you cannot do mallocs
         and such in the constructors.  */
 
-      if (main_sym != (symbol_info_t *)0
+      if (main_sym != (symbol_info_t *) 0
          && ((hdr.moh_flags & MOH_EXECABLE_F) == 0))
        add_func_table (&hdr, load_array, main_sym, FNTC_INITIALIZATION);
 
@@ -2896,7 +3008,7 @@ scan_prog_file (prog_name, which_pass)
          if (debug)
            print_load_command (load_hdr, offset, i);
 
-         bcopy ((char *)load_hdr, (char *)(obj + offset), size);
+         bcopy ((char *) load_hdr, (char *) (obj + offset), size);
          offset += size;
        }
     }
@@ -2935,7 +3047,7 @@ add_func_table (hdr_p, load_array, sym, type)
 
   load_cmd = &load_array[load_index];
   load_cmd->load = ptr;
-  load_cmd->section = (char *)0;
+  load_cmd->section = (char *) 0;
 
   /* Fill in func table load command.  */
   ptr->func.ldc_header.ldci_cmd_type = LDC_FUNC_TABLE;
@@ -3044,7 +3156,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;
+  char *type_str = (char *) 0;
 
   switch (type)
     {
@@ -3069,7 +3181,7 @@ print_load_command (load_hdr, offset, number)
           (long) load_hdr->hdr.ldci_section_off,
           (long) load_hdr->hdr.ldci_section_len);
 
-  if (type_str == (char *)0)
+  if (type_str == (char *) 0)
     fprintf (stderr, ", ty: unknown (%ld)\n", (long) type);
 
   else if (type != LDC_REGION)
@@ -3108,7 +3220,7 @@ static void
 bad_header (status)
      int status;
 {
-  char *msg = (char *)0;
+  char *msg = (char *) 0;
 
   switch (status)
     {
@@ -3120,7 +3232,7 @@ bad_header (status)
     case MO_ERROR_UNSUPPORTED_VERS:    msg = "unsupported version";            break;
     }
 
-  if (msg == (char *)0)
+  if (msg == (char *) 0)
     fatal ("unknown {de,en}code_mach_o_hdr return value %d", status);
   else
     fatal ("%s", msg);
@@ -3158,14 +3270,14 @@ read_file (name, fd, rw)
     page_size = sysconf (_SC_PAGE_SIZE);
 
   p->rounded_size = ((p->size + page_size - 1) / page_size) * page_size;
-  p->start = mmap ((caddr_t)0,
+  p->start = mmap ((caddr_t) 0,
                   (rw) ? p->rounded_size : p->size,
                   (rw) ? (PROT_READ | PROT_WRITE) : PROT_READ,
                   MAP_FILE | MAP_VARIABLE | MAP_SHARED,
                   fd,
                   0L);
 
-  if (p->start != (char *)0 && p->start != (char *)-1)
+  if (p->start != (char *) 0 && p->start != (char *) -1)
     p->use_mmap = 1;
 
   else
@@ -3231,7 +3343,7 @@ end_file (ptr)
 
          len = write (ptr->fd, ptr->start, ptr->size);
          if (len < 0)
-           fatal_perror ("read %s", ptr->name);
+           fatal_perror ("write %s", ptr->name);
 
          if (len != ptr->size)
            fatal ("wrote %ld bytes, expected %ld, to %s", len, ptr->size, ptr->name);