Bring in a trimmed down gcc-3.4-20040618.
[dragonfly.git] / contrib / gcc-3.4 / gcc / collect2.c
1 /* Collect static initialization info into data structures that can be
2    traversed by C++ initialization and finalization routines.
3    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998,
4    1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
5    Contributed by Chris Smith (csmith@convex.com).
6    Heavily modified by Michael Meissner (meissner@cygnus.com),
7    Per Bothner (bothner@cygnus.com), and John Gilmore (gnu@cygnus.com).
8
9 This file is part of GCC.
10
11 GCC is free software; you can redistribute it and/or modify it under
12 the terms of the GNU General Public License as published by the Free
13 Software Foundation; either version 2, or (at your option) any later
14 version.
15
16 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
17 WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
19 for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with GCC; see the file COPYING.  If not, write to the Free
23 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
24 02111-1307, USA.  */
25
26
27 /* Build tables of static constructors and destructors and run ld.  */
28
29 #include "config.h"
30 #include "system.h"
31 #include "coretypes.h"
32 #include "tm.h"
33 #include <signal.h>
34 #if ! defined( SIGCHLD ) && defined( SIGCLD )
35 #  define SIGCHLD SIGCLD
36 #endif
37
38 #ifdef vfork /* Autoconf may define this to fork for us.  */
39 # define VFORK_STRING "fork"
40 #else
41 # define VFORK_STRING "vfork"
42 #endif
43 #ifdef HAVE_VFORK_H
44 #include <vfork.h>
45 #endif
46 #ifdef VMS
47 #define vfork() (decc$$alloc_vfork_blocks() >= 0 ? \
48                lib$get_current_invo_context(decc$$get_vfork_jmpbuf()) : -1)
49 #endif /* VMS */
50
51 #ifndef LIBRARY_PATH_ENV
52 #define LIBRARY_PATH_ENV "LIBRARY_PATH"
53 #endif
54
55 #define COLLECT
56
57 #include "collect2.h"
58 #include "demangle.h"
59 #include "obstack.h"
60 #include "intl.h"
61 #include "version.h"
62 \f
63 /* On certain systems, we have code that works by scanning the object file
64    directly.  But this code uses system-specific header files and library
65    functions, so turn it off in a cross-compiler.  Likewise, the names of
66    the utilities are not correct for a cross-compiler; we have to hope that
67    cross-versions are in the proper directories.  */
68
69 #ifdef CROSS_COMPILE
70 #undef SUNOS4_SHARED_LIBRARIES
71 #undef OBJECT_FORMAT_COFF
72 #undef MD_EXEC_PREFIX
73 #undef REAL_LD_FILE_NAME
74 #undef REAL_NM_FILE_NAME
75 #undef REAL_STRIP_FILE_NAME
76 #endif
77
78 /* If we cannot use a special method, use the ordinary one:
79    run nm to find what symbols are present.
80    In a cross-compiler, this means you need a cross nm,
81    but that is not quite as unpleasant as special headers.  */
82
83 #if !defined (OBJECT_FORMAT_COFF)
84 #define OBJECT_FORMAT_NONE
85 #endif
86
87 #ifdef OBJECT_FORMAT_COFF
88
89 #include <a.out.h>
90 #include <ar.h>
91
92 #ifdef UMAX
93 #include <sgs.h>
94 #endif
95
96 /* Many versions of ldfcn.h define these.  */
97 #ifdef FREAD
98 #undef FREAD
99 #undef FWRITE
100 #endif
101
102 #include <ldfcn.h>
103
104 /* Some systems have an ISCOFF macro, but others do not.  In some cases
105    the macro may be wrong.  MY_ISCOFF is defined in tm.h files for machines
106    that either do not have an ISCOFF macro in /usr/include or for those
107    where it is wrong.  */
108
109 #ifndef MY_ISCOFF
110 #define MY_ISCOFF(X) ISCOFF (X)
111 #endif
112
113 #endif /* OBJECT_FORMAT_COFF */
114
115 #ifdef OBJECT_FORMAT_NONE
116
117 /* Default flags to pass to nm.  */
118 #ifndef NM_FLAGS
119 #define NM_FLAGS "-n"
120 #endif
121
122 #endif /* OBJECT_FORMAT_NONE */
123
124 /* Some systems use __main in a way incompatible with its use in gcc, in these
125    cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
126    give the same symbol without quotes for an alternative entry point.  */
127 #ifndef NAME__MAIN
128 #define NAME__MAIN "__main"
129 #endif
130
131 /* This must match tree.h.  */
132 #define DEFAULT_INIT_PRIORITY 65535
133
134 #ifndef COLLECT_SHARED_INIT_FUNC
135 #define COLLECT_SHARED_INIT_FUNC(STREAM, FUNC) \
136   fprintf ((STREAM), "void _GLOBAL__DI() {\n\t%s();\n}\n", (FUNC))
137 #endif
138 #ifndef COLLECT_SHARED_FINI_FUNC
139 #define COLLECT_SHARED_FINI_FUNC(STREAM, FUNC) \
140   fprintf ((STREAM), "void _GLOBAL__DD() {\n\t%s();\n}\n", (FUNC))
141 #endif
142
143 #if defined (LDD_SUFFIX) || SUNOS4_SHARED_LIBRARIES
144 #define SCAN_LIBRARIES
145 #endif
146
147 #ifdef USE_COLLECT2
148 int do_collecting = 1;
149 #else
150 int do_collecting = 0;
151 #endif
152
153 #ifndef COLLECT_PARSE_FLAG
154 #define COLLECT_PARSE_FLAG(FLAG)
155 #endif
156
157 /* Nonzero if we should suppress the automatic demangling of identifiers
158    in linker error messages.  Set from COLLECT_NO_DEMANGLE.  */
159 int no_demangle;
160 \f
161 /* Linked lists of constructor and destructor names.  */
162
163 struct id
164 {
165   struct id *next;
166   int sequence;
167   char name[1];
168 };
169
170 struct head
171 {
172   struct id *first;
173   struct id *last;
174   int number;
175 };
176
177 /* Enumeration giving which pass this is for scanning the program file.  */
178
179 enum pass {
180   PASS_FIRST,                           /* without constructors */
181   PASS_OBJ,                             /* individual objects */
182   PASS_LIB,                             /* looking for shared libraries */
183   PASS_SECOND                           /* with constructors linked in */
184 };
185
186 int vflag;                              /* true if -v */
187 static int rflag;                       /* true if -r */
188 static int strip_flag;                  /* true if -s */
189 #ifdef COLLECT_EXPORT_LIST
190 static int export_flag;                 /* true if -bE */
191 static int aix64_flag;                  /* true if -b64 */
192 #endif
193
194 int debug;                              /* true if -debug */
195
196 static int shared_obj;                  /* true if -shared */
197
198 static const char *c_file;              /* <xxx>.c for constructor/destructor list.  */
199 static const char *o_file;              /* <xxx>.o for constructor/destructor list.  */
200 #ifdef COLLECT_EXPORT_LIST
201 static const char *export_file;         /* <xxx>.x for AIX export list.  */
202 #endif
203 const char *ldout;                      /* File for ld errors.  */
204 static const char *output_file;         /* Output file for ld.  */
205 static const char *nm_file_name;        /* pathname of nm */
206 #ifdef LDD_SUFFIX
207 static const char *ldd_file_name;       /* pathname of ldd (or equivalent) */
208 #endif
209 static const char *strip_file_name;             /* pathname of strip */
210 const char *c_file_name;                /* pathname of gcc */
211 static char *initname, *fininame;       /* names of init and fini funcs */
212
213 static struct head constructors;        /* list of constructors found */
214 static struct head destructors;         /* list of destructors found */
215 #ifdef COLLECT_EXPORT_LIST
216 static struct head exports;             /* list of exported symbols */
217 #endif
218 static struct head frame_tables;        /* list of frame unwind info tables */
219
220 struct obstack temporary_obstack;
221 char * temporary_firstobj;
222
223 /* Holds the return value of pexecute and fork.  */
224 int pid;
225
226 /* Structure to hold all the directories in which to search for files to
227    execute.  */
228
229 struct prefix_list
230 {
231   const char *prefix;         /* String to prepend to the path.  */
232   struct prefix_list *next;   /* Next in linked list.  */
233 };
234
235 struct path_prefix
236 {
237   struct prefix_list *plist;  /* List of prefixes to try */
238   int max_len;                /* Max length of a prefix in PLIST */
239   const char *name;           /* Name of this list (used in config stuff) */
240 };
241
242 #ifdef COLLECT_EXPORT_LIST
243 /* Lists to keep libraries to be scanned for global constructors/destructors.  */
244 static struct head libs;                    /* list of libraries */
245 static struct path_prefix cmdline_lib_dirs; /* directories specified with -L */
246 static struct path_prefix libpath_lib_dirs; /* directories in LIBPATH */
247 static struct path_prefix *libpaths[3] = {&cmdline_lib_dirs,
248                                           &libpath_lib_dirs, NULL};
249 static const char *const libexts[3] = {"a", "so", NULL};  /* possible library extensions */
250 #endif
251
252 static void handler (int);
253 static int is_ctor_dtor (const char *);
254 static char *find_a_file (struct path_prefix *, const char *);
255 static void add_prefix (struct path_prefix *, const char *);
256 static void prefix_from_env (const char *, struct path_prefix *);
257 static void prefix_from_string (const char *, struct path_prefix *);
258 static void do_wait (const char *);
259 static void fork_execute (const char *, char **);
260 static void maybe_unlink (const char *);
261 static void add_to_list (struct head *, const char *);
262 static int extract_init_priority (const char *);
263 static void sort_ids (struct head *);
264 static void write_list (FILE *, const char *, struct id *);
265 #ifdef COLLECT_EXPORT_LIST
266 static void dump_list (FILE *, const char *, struct id *);
267 #endif
268 #if 0
269 static void dump_prefix_list (FILE *, const char *, struct prefix_list *);
270 #endif
271 static void write_list_with_asm (FILE *, const char *, struct id *);
272 static void write_c_file (FILE *, const char *);
273 static void write_c_file_stat (FILE *, const char *);
274 #ifndef LD_INIT_SWITCH
275 static void write_c_file_glob (FILE *, const char *);
276 #endif
277 static void scan_prog_file (const char *, enum pass);
278 #ifdef SCAN_LIBRARIES
279 static void scan_libraries (const char *);
280 #endif
281 #if LINK_ELIMINATE_DUPLICATE_LDIRECTORIES
282 static int is_in_args (const char *, const char **, const char **);
283 #endif
284 #ifdef COLLECT_EXPORT_LIST
285 #if 0
286 static int is_in_list (const char *, struct id *);
287 #endif
288 static void write_aix_file (FILE *, struct id *);
289 static char *resolve_lib_name (const char *);
290 #endif
291 static char *extract_string (const char **);
292 \f
293 #ifndef HAVE_DUP2
294 static int
295 dup2 (int oldfd, int newfd)
296 {
297   int fdtmp[256];
298   int fdx = 0;
299   int fd;
300
301   if (oldfd == newfd)
302     return oldfd;
303   close (newfd);
304   while ((fd = dup (oldfd)) != newfd && fd >= 0) /* good enough for low fd's */
305     fdtmp[fdx++] = fd;
306   while (fdx > 0)
307     close (fdtmp[--fdx]);
308
309   return fd;
310 }
311 #endif /* ! HAVE_DUP2 */
312 \f
313 /* Delete tempfiles and exit function.  */
314
315 void
316 collect_exit (int status)
317 {
318   if (c_file != 0 && c_file[0])
319     maybe_unlink (c_file);
320
321   if (o_file != 0 && o_file[0])
322     maybe_unlink (o_file);
323
324 #ifdef COLLECT_EXPORT_LIST
325   if (export_file != 0 && export_file[0])
326     maybe_unlink (export_file);
327 #endif
328
329   if (ldout != 0 && ldout[0])
330     {
331       dump_file (ldout);
332       maybe_unlink (ldout);
333     }
334
335   if (status != 0 && output_file != 0 && output_file[0])
336     maybe_unlink (output_file);
337
338   exit (status);
339 }
340
341 \f
342 /* Notify user of a non-error.  */
343 void
344 notice (const char *msgid, ...)
345 {
346   va_list ap;
347
348   va_start (ap, msgid);
349   vfprintf (stderr, _(msgid), ap);
350   va_end (ap);
351 }
352
353 /* Die when sys call fails.  */
354
355 void
356 fatal_perror (const char * msgid, ...)
357 {
358   int e = errno;
359   va_list ap;
360
361   va_start (ap, msgid);
362   fprintf (stderr, "collect2: ");
363   vfprintf (stderr, _(msgid), ap);
364   fprintf (stderr, ": %s\n", xstrerror (e));
365   va_end (ap);
366
367   collect_exit (FATAL_EXIT_CODE);
368 }
369
370 /* Just die.  */
371
372 void
373 fatal (const char * msgid, ...)
374 {
375   va_list ap;
376
377   va_start (ap, msgid);
378   fprintf (stderr, "collect2: ");
379   vfprintf (stderr, _(msgid), ap);
380   fprintf (stderr, "\n");
381   va_end (ap);
382
383   collect_exit (FATAL_EXIT_CODE);
384 }
385
386 /* Write error message.  */
387
388 void
389 error (const char * msgid, ...)
390 {
391   va_list ap;
392
393   va_start (ap, msgid);
394   fprintf (stderr, "collect2: ");
395   vfprintf (stderr, _(msgid), ap);
396   fprintf (stderr, "\n");
397   va_end(ap);
398 }
399
400 /* In case obstack is linked in, and abort is defined to fancy_abort,
401    provide a default entry.  */
402
403 void
404 fancy_abort (void)
405 {
406   fatal ("internal error");
407 }
408 \f
409 static void
410 handler (int signo)
411 {
412   if (c_file != 0 && c_file[0])
413     maybe_unlink (c_file);
414
415   if (o_file != 0 && o_file[0])
416     maybe_unlink (o_file);
417
418   if (ldout != 0 && ldout[0])
419     maybe_unlink (ldout);
420
421 #ifdef COLLECT_EXPORT_LIST
422   if (export_file != 0 && export_file[0])
423     maybe_unlink (export_file);
424 #endif
425
426   signal (signo, SIG_DFL);
427   kill (getpid (), signo);
428 }
429
430 \f
431 int
432 file_exists (const char *name)
433 {
434   return access (name, R_OK) == 0;
435 }
436
437 /* Parse a reasonable subset of shell quoting syntax.  */
438
439 static char *
440 extract_string (const char **pp)
441 {
442   const char *p = *pp;
443   int backquote = 0;
444   int inside = 0;
445
446   for (;;)
447     {
448       char c = *p;
449       if (c == '\0')
450         break;
451       ++p;
452       if (backquote)
453         obstack_1grow (&temporary_obstack, c);
454       else if (! inside && c == ' ')
455         break;
456       else if (! inside && c == '\\')
457         backquote = 1;
458       else if (c == '\'')
459         inside = !inside;
460       else
461         obstack_1grow (&temporary_obstack, c);
462     }
463
464   obstack_1grow (&temporary_obstack, '\0');
465   *pp = p;
466   return obstack_finish (&temporary_obstack);
467 }
468 \f
469 void
470 dump_file (const char *name)
471 {
472   FILE *stream = fopen (name, "r");
473
474   if (stream == 0)
475     return;
476   while (1)
477     {
478       int c;
479       while (c = getc (stream),
480              c != EOF && (ISIDNUM (c) || c == '$' || c == '.'))
481         obstack_1grow (&temporary_obstack, c);
482       if (obstack_object_size (&temporary_obstack) > 0)
483         {
484           const char *word, *p;
485           char *result;
486           obstack_1grow (&temporary_obstack, '\0');
487           word = obstack_finish (&temporary_obstack);
488
489           if (*word == '.')
490             ++word, putc ('.', stderr);
491           p = word;
492           if (!strncmp (p, USER_LABEL_PREFIX, strlen (USER_LABEL_PREFIX)))
493             p += strlen (USER_LABEL_PREFIX);
494
495           if (no_demangle)
496             result = 0;
497           else
498             result = cplus_demangle (p, DMGL_PARAMS | DMGL_ANSI | DMGL_VERBOSE);
499
500           if (result)
501             {
502               int diff;
503               fputs (result, stderr);
504
505               diff = strlen (word) - strlen (result);
506               while (diff > 0 && c == ' ')
507                 --diff, putc (' ', stderr);
508               while (diff < 0 && c == ' ')
509                 ++diff, c = getc (stream);
510
511               free (result);
512             }
513           else
514             fputs (word, stderr);
515
516           fflush (stderr);
517           obstack_free (&temporary_obstack, temporary_firstobj);
518         }
519       if (c == EOF)
520         break;
521       putc (c, stderr);
522     }
523   fclose (stream);
524 }
525 \f
526 /* Decide whether the given symbol is: a constructor (1), a destructor
527    (2), a routine in a shared object that calls all the constructors
528    (3) or destructors (4), a DWARF exception-handling table (5), or
529    nothing special (0).  */
530
531 static int
532 is_ctor_dtor (const char *s)
533 {
534   struct names { const char *const name; const int len; const int ret;
535     const int two_underscores; };
536
537   const struct names *p;
538   int ch;
539   const char *orig_s = s;
540
541   static const struct names special[] = {
542 #ifndef NO_DOLLAR_IN_LABEL
543     { "GLOBAL__I$", sizeof ("GLOBAL__I$")-1, 1, 0 },
544     { "GLOBAL__D$", sizeof ("GLOBAL__D$")-1, 2, 0 },
545 #else
546 #ifndef NO_DOT_IN_LABEL
547     { "GLOBAL__I.", sizeof ("GLOBAL__I.")-1, 1, 0 },
548     { "GLOBAL__D.", sizeof ("GLOBAL__D.")-1, 2, 0 },
549 #endif /* NO_DOT_IN_LABEL */
550 #endif /* NO_DOLLAR_IN_LABEL */
551     { "GLOBAL__I_", sizeof ("GLOBAL__I_")-1, 1, 0 },
552     { "GLOBAL__D_", sizeof ("GLOBAL__D_")-1, 2, 0 },
553     { "GLOBAL__F_", sizeof ("GLOBAL__F_")-1, 5, 0 },
554     { "GLOBAL__FI_", sizeof ("GLOBAL__FI_")-1, 3, 0 },
555     { "GLOBAL__FD_", sizeof ("GLOBAL__FD_")-1, 4, 0 },
556     { NULL, 0, 0, 0 }
557   };
558
559   while ((ch = *s) == '_')
560     ++s;
561
562   if (s == orig_s)
563     return 0;
564
565   for (p = &special[0]; p->len > 0; p++)
566     {
567       if (ch == p->name[0]
568           && (!p->two_underscores || ((s - orig_s) >= 2))
569           && strncmp(s, p->name, p->len) == 0)
570         {
571           return p->ret;
572         }
573     }
574   return 0;
575 }
576 \f
577 /* We maintain two prefix lists: one from COMPILER_PATH environment variable
578    and one from the PATH variable.  */
579
580 static struct path_prefix cpath, path;
581
582 #ifdef CROSS_COMPILE
583 /* This is the name of the target machine.  We use it to form the name
584    of the files to execute.  */
585
586 static const char *const target_machine = TARGET_MACHINE;
587 #endif
588
589 /* Search for NAME using prefix list PPREFIX.  We only look for executable
590    files.
591
592    Return 0 if not found, otherwise return its name, allocated with malloc.  */
593
594 static char *
595 find_a_file (struct path_prefix *pprefix, const char *name)
596 {
597   char *temp;
598   struct prefix_list *pl;
599   int len = pprefix->max_len + strlen (name) + 1;
600
601   if (debug)
602     fprintf (stderr, "Looking for '%s'\n", name);
603
604 #ifdef HOST_EXECUTABLE_SUFFIX
605   len += strlen (HOST_EXECUTABLE_SUFFIX);
606 #endif
607
608   temp = xmalloc (len);
609
610   /* Determine the filename to execute (special case for absolute paths).  */
611
612   if (*name == '/'
613 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
614       || (*name && name[1] == ':')
615 #endif
616       )
617     {
618       if (access (name, X_OK) == 0)
619         {
620           strcpy (temp, name);
621
622           if (debug)
623             fprintf (stderr, "  - found: absolute path\n");
624
625           return temp;
626         }
627
628 #ifdef HOST_EXECUTABLE_SUFFIX
629         /* Some systems have a suffix for executable files.
630            So try appending that.  */
631       strcpy (temp, name);
632         strcat (temp, HOST_EXECUTABLE_SUFFIX);
633
634         if (access (temp, X_OK) == 0)
635           return temp;
636 #endif
637
638       if (debug)
639         fprintf (stderr, "  - failed to locate using absolute path\n");
640     }
641   else
642     for (pl = pprefix->plist; pl; pl = pl->next)
643       {
644         struct stat st;
645
646         strcpy (temp, pl->prefix);
647         strcat (temp, name);
648
649         if (stat (temp, &st) >= 0
650             && ! S_ISDIR (st.st_mode)
651             && access (temp, X_OK) == 0)
652           return temp;
653
654 #ifdef HOST_EXECUTABLE_SUFFIX
655         /* Some systems have a suffix for executable files.
656            So try appending that.  */
657         strcat (temp, HOST_EXECUTABLE_SUFFIX);
658
659         if (stat (temp, &st) >= 0
660             && ! S_ISDIR (st.st_mode)
661             && access (temp, X_OK) == 0)
662           return temp;
663 #endif
664       }
665
666   if (debug && pprefix->plist == NULL)
667     fprintf (stderr, "  - failed: no entries in prefix list\n");
668
669   free (temp);
670   return 0;
671 }
672
673 /* Add an entry for PREFIX to prefix list PPREFIX.  */
674
675 static void
676 add_prefix (struct path_prefix *pprefix, const char *prefix)
677 {
678   struct prefix_list *pl, **prev;
679   int len;
680
681   if (pprefix->plist)
682     {
683       for (pl = pprefix->plist; pl->next; pl = pl->next)
684         ;
685       prev = &pl->next;
686     }
687   else
688     prev = &pprefix->plist;
689
690   /* Keep track of the longest prefix.  */
691
692   len = strlen (prefix);
693   if (len > pprefix->max_len)
694     pprefix->max_len = len;
695
696   pl = xmalloc (sizeof (struct prefix_list));
697   pl->prefix = xstrdup (prefix);
698
699   if (*prev)
700     pl->next = *prev;
701   else
702     pl->next = (struct prefix_list *) 0;
703   *prev = pl;
704 }
705 \f
706 /* Take the value of the environment variable ENV, break it into a path, and
707    add of the entries to PPREFIX.  */
708
709 static void
710 prefix_from_env (const char *env, struct path_prefix *pprefix)
711 {
712   const char *p;
713   GET_ENVIRONMENT (p, env);
714
715   if (p)
716     prefix_from_string (p, pprefix);
717 }
718
719 static void
720 prefix_from_string (const char *p, struct path_prefix *pprefix)
721 {
722   const char *startp, *endp;
723   char *nstore = xmalloc (strlen (p) + 3);
724
725   if (debug)
726     fprintf (stderr, "Convert string '%s' into prefixes, separator = '%c'\n", p, PATH_SEPARATOR);
727
728   startp = endp = p;
729   while (1)
730     {
731       if (*endp == PATH_SEPARATOR || *endp == 0)
732         {
733           strncpy (nstore, startp, endp-startp);
734           if (endp == startp)
735             {
736               strcpy (nstore, "./");
737             }
738           else if (! IS_DIR_SEPARATOR (endp[-1]))
739             {
740               nstore[endp-startp] = DIR_SEPARATOR;
741               nstore[endp-startp+1] = 0;
742             }
743           else
744             nstore[endp-startp] = 0;
745
746           if (debug)
747             fprintf (stderr, "  - add prefix: %s\n", nstore);
748
749           add_prefix (pprefix, nstore);
750           if (*endp == 0)
751             break;
752           endp = startp = endp + 1;
753         }
754       else
755         endp++;
756     }
757 }
758 \f
759 /* Main program.  */
760
761 int
762 main (int argc, char **argv)
763 {
764   static const char *const ld_suffix    = "ld";
765   static const char *const real_ld_suffix = "real-ld";
766   static const char *const collect_ld_suffix = "collect-ld";
767   static const char *const nm_suffix    = "nm";
768   static const char *const gnm_suffix   = "gnm";
769 #ifdef LDD_SUFFIX
770   static const char *const ldd_suffix   = LDD_SUFFIX;
771 #endif
772   static const char *const strip_suffix = "strip";
773   static const char *const gstrip_suffix = "gstrip";
774
775 #ifdef CROSS_COMPILE
776   /* If we look for a program in the compiler directories, we just use
777      the short name, since these directories are already system-specific.
778      But it we look for a program in the system directories, we need to
779      qualify the program name with the target machine.  */
780
781   const char *const full_ld_suffix =
782     concat(target_machine, "-", ld_suffix, NULL);
783   const char *const full_nm_suffix =
784     concat (target_machine, "-", nm_suffix, NULL);
785   const char *const full_gnm_suffix =
786     concat (target_machine, "-", gnm_suffix, NULL);
787 #ifdef LDD_SUFFIX
788   const char *const full_ldd_suffix =
789     concat (target_machine, "-", ldd_suffix, NULL);
790 #endif
791   const char *const full_strip_suffix =
792     concat (target_machine, "-", strip_suffix, NULL);
793   const char *const full_gstrip_suffix =
794     concat (target_machine, "-", gstrip_suffix, NULL);
795 #else
796   const char *const full_ld_suffix      = ld_suffix;
797   const char *const full_nm_suffix      = nm_suffix;
798   const char *const full_gnm_suffix     = gnm_suffix;
799 #ifdef LDD_SUFFIX
800   const char *const full_ldd_suffix     = ldd_suffix;
801 #endif
802   const char *const full_strip_suffix   = strip_suffix;
803   const char *const full_gstrip_suffix  = gstrip_suffix;
804 #endif /* CROSS_COMPILE */
805
806   const char *arg;
807   FILE *outf;
808 #ifdef COLLECT_EXPORT_LIST
809   FILE *exportf;
810 #endif
811   const char *ld_file_name;
812   const char *p;
813   char **c_argv;
814   const char **c_ptr;
815   char **ld1_argv;
816   const char **ld1;
817   char **ld2_argv;
818   const char **ld2;
819   char **object_lst;
820   const char **object;
821   int first_file;
822   int num_c_args        = argc+9;
823
824   no_demangle = !! getenv ("COLLECT_NO_DEMANGLE");
825
826   /* Suppress demangling by the real linker, which may be broken.  */
827   putenv (xstrdup ("COLLECT_NO_DEMANGLE="));
828
829 #if defined (COLLECT2_HOST_INITIALIZATION)
830   /* Perform system dependent initialization, if necessary.  */
831   COLLECT2_HOST_INITIALIZATION;
832 #endif
833
834 #ifdef SIGCHLD
835   /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will
836      receive the signal.  A different setting is inheritable */
837   signal (SIGCHLD, SIG_DFL);
838 #endif
839
840   gcc_init_libintl ();
841
842   /* Do not invoke xcalloc before this point, since locale needs to be
843      set first, in case a diagnostic is issued.  */
844
845   ld1 = (const char **)(ld1_argv = xcalloc(sizeof (char *), argc+3));
846   ld2 = (const char **)(ld2_argv = xcalloc(sizeof (char *), argc+10));
847   object = (const char **)(object_lst = xcalloc(sizeof (char *), argc));
848
849 #ifdef DEBUG
850   debug = 1;
851 #endif
852
853   /* Parse command line early for instances of -debug.  This allows
854      the debug flag to be set before functions like find_a_file()
855      are called.  */
856   {
857     int i;
858
859     for (i = 1; argv[i] != NULL; i ++)
860       {
861         if (! strcmp (argv[i], "-debug"))
862           debug = 1;
863         COLLECT_PARSE_FLAG (argv[i]);
864       }
865     vflag = debug;
866   }
867
868 #ifndef DEFAULT_A_OUT_NAME
869   output_file = "a.out";
870 #else
871   output_file = DEFAULT_A_OUT_NAME;
872 #endif
873
874   obstack_begin (&temporary_obstack, 0);
875   temporary_firstobj = obstack_alloc (&temporary_obstack, 0);
876
877   current_demangling_style = auto_demangling;
878   p = getenv ("COLLECT_GCC_OPTIONS");
879   while (p && *p)
880     {
881       const char *q = extract_string (&p);
882       if (*q == '-' && (q[1] == 'm' || q[1] == 'f'))
883         num_c_args++;
884     }
885   obstack_free (&temporary_obstack, temporary_firstobj);
886
887   /* -fno-profile-arcs -fno-test-coverage -fno-branch-probabilities
888      -fno-exceptions -w */
889   num_c_args += 5;
890
891   c_ptr = (const char **) (c_argv = xcalloc (sizeof (char *), num_c_args));
892
893   if (argc < 2)
894     fatal ("no arguments");
895
896 #ifdef SIGQUIT
897   if (signal (SIGQUIT, SIG_IGN) != SIG_IGN)
898     signal (SIGQUIT, handler);
899 #endif
900   if (signal (SIGINT, SIG_IGN) != SIG_IGN)
901     signal (SIGINT, handler);
902 #ifdef SIGALRM
903   if (signal (SIGALRM, SIG_IGN) != SIG_IGN)
904     signal (SIGALRM, handler);
905 #endif
906 #ifdef SIGHUP
907   if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
908     signal (SIGHUP, handler);
909 #endif
910   if (signal (SIGSEGV, SIG_IGN) != SIG_IGN)
911     signal (SIGSEGV, handler);
912 #ifdef SIGBUS
913   if (signal (SIGBUS, SIG_IGN) != SIG_IGN)
914     signal (SIGBUS, handler);
915 #endif
916
917   /* Extract COMPILER_PATH and PATH into our prefix list.  */
918   prefix_from_env ("COMPILER_PATH", &cpath);
919   prefix_from_env ("PATH", &path);
920
921   /* Try to discover a valid linker/nm/strip to use.  */
922
923   /* Maybe we know the right file to use (if not cross).  */
924   ld_file_name = 0;
925 #ifdef DEFAULT_LINKER
926   if (access (DEFAULT_LINKER, X_OK) == 0)
927     ld_file_name = DEFAULT_LINKER;
928   if (ld_file_name == 0)
929 #endif
930 #ifdef REAL_LD_FILE_NAME
931   ld_file_name = find_a_file (&path, REAL_LD_FILE_NAME);
932   if (ld_file_name == 0)
933 #endif
934   /* Search the (target-specific) compiler dirs for ld'.  */
935   ld_file_name = find_a_file (&cpath, real_ld_suffix);
936   /* Likewise for `collect-ld'.  */
937   if (ld_file_name == 0)
938     ld_file_name = find_a_file (&cpath, collect_ld_suffix);
939   /* Search the compiler directories for `ld'.  We have protection against
940      recursive calls in find_a_file.  */
941   if (ld_file_name == 0)
942     ld_file_name = find_a_file (&cpath, ld_suffix);
943   /* Search the ordinary system bin directories
944      for `ld' (if native linking) or `TARGET-ld' (if cross).  */
945   if (ld_file_name == 0)
946     ld_file_name = find_a_file (&path, full_ld_suffix);
947
948 #ifdef REAL_NM_FILE_NAME
949   nm_file_name = find_a_file (&path, REAL_NM_FILE_NAME);
950   if (nm_file_name == 0)
951 #endif
952   nm_file_name = find_a_file (&cpath, gnm_suffix);
953   if (nm_file_name == 0)
954     nm_file_name = find_a_file (&path, full_gnm_suffix);
955   if (nm_file_name == 0)
956     nm_file_name = find_a_file (&cpath, nm_suffix);
957   if (nm_file_name == 0)
958     nm_file_name = find_a_file (&path, full_nm_suffix);
959
960 #ifdef LDD_SUFFIX
961   ldd_file_name = find_a_file (&cpath, ldd_suffix);
962   if (ldd_file_name == 0)
963     ldd_file_name = find_a_file (&path, full_ldd_suffix);
964 #endif
965
966 #ifdef REAL_STRIP_FILE_NAME
967   strip_file_name = find_a_file (&path, REAL_STRIP_FILE_NAME);
968   if (strip_file_name == 0)
969 #endif
970   strip_file_name = find_a_file (&cpath, gstrip_suffix);
971   if (strip_file_name == 0)
972     strip_file_name = find_a_file (&path, full_gstrip_suffix);
973   if (strip_file_name == 0)
974     strip_file_name = find_a_file (&cpath, strip_suffix);
975   if (strip_file_name == 0)
976     strip_file_name = find_a_file (&path, full_strip_suffix);
977
978   /* Determine the full path name of the C compiler to use.  */
979   c_file_name = getenv ("COLLECT_GCC");
980   if (c_file_name == 0)
981     {
982 #ifdef CROSS_COMPILE
983       c_file_name = concat (target_machine, "-gcc", NULL);
984 #else
985       c_file_name = "gcc";
986 #endif
987     }
988
989   p = find_a_file (&cpath, c_file_name);
990
991   /* Here it should be safe to use the system search path since we should have
992      already qualified the name of the compiler when it is needed.  */
993   if (p == 0)
994     p = find_a_file (&path, c_file_name);
995
996   if (p)
997     c_file_name = p;
998
999   *ld1++ = *ld2++ = ld_file_name;
1000
1001   /* Make temp file names.  */
1002   c_file = make_temp_file (".c");
1003   o_file = make_temp_file (".o");
1004 #ifdef COLLECT_EXPORT_LIST
1005   export_file = make_temp_file (".x");
1006 #endif
1007   ldout = make_temp_file (".ld");
1008   *c_ptr++ = c_file_name;
1009   *c_ptr++ = "-x";
1010   *c_ptr++ = "c";
1011   *c_ptr++ = "-c";
1012   *c_ptr++ = "-o";
1013   *c_ptr++ = o_file;
1014
1015 #ifdef COLLECT_EXPORT_LIST
1016   /* Generate a list of directories from LIBPATH.  */
1017   prefix_from_env ("LIBPATH", &libpath_lib_dirs);
1018   /* Add to this list also two standard directories where
1019      AIX loader always searches for libraries.  */
1020   add_prefix (&libpath_lib_dirs, "/lib");
1021   add_prefix (&libpath_lib_dirs, "/usr/lib");
1022 #endif
1023
1024   /* Get any options that the upper GCC wants to pass to the sub-GCC.
1025
1026      AIX support needs to know if -shared has been specified before
1027      parsing commandline arguments.  */
1028
1029   p = getenv ("COLLECT_GCC_OPTIONS");
1030   while (p && *p)
1031     {
1032       const char *q = extract_string (&p);
1033       if (*q == '-' && (q[1] == 'm' || q[1] == 'f'))
1034         *c_ptr++ = xstrdup (q);
1035       if (strcmp (q, "-EL") == 0 || strcmp (q, "-EB") == 0)
1036         *c_ptr++ = xstrdup (q);
1037       if (strcmp (q, "-shared") == 0)
1038         shared_obj = 1;
1039       if (*q == '-' && q[1] == 'B')
1040         {
1041           *c_ptr++ = xstrdup (q);
1042           if (q[2] == 0)
1043             {
1044               q = extract_string (&p);
1045               *c_ptr++ = xstrdup (q);
1046             }
1047         }
1048     }
1049   obstack_free (&temporary_obstack, temporary_firstobj);
1050   *c_ptr++ = "-fno-profile-arcs";
1051   *c_ptr++ = "-fno-test-coverage";
1052   *c_ptr++ = "-fno-branch-probabilities";
1053   *c_ptr++ = "-fno-exceptions";
1054   *c_ptr++ = "-w";
1055
1056   /* !!! When GCC calls collect2,
1057      it does not know whether it is calling collect2 or ld.
1058      So collect2 cannot meaningfully understand any options
1059      except those ld understands.
1060      If you propose to make GCC pass some other option,
1061      just imagine what will happen if ld is really ld!!!  */
1062
1063   /* Parse arguments.  Remember output file spec, pass the rest to ld.  */
1064   /* After the first file, put in the c++ rt0.  */
1065
1066   first_file = 1;
1067   while ((arg = *++argv) != (char *) 0)
1068     {
1069       *ld1++ = *ld2++ = arg;
1070
1071       if (arg[0] == '-')
1072         {
1073           switch (arg[1])
1074             {
1075 #ifdef COLLECT_EXPORT_LIST
1076             /* We want to disable automatic exports on AIX when user
1077                explicitly puts an export list in command line */
1078             case 'b':
1079               if (arg[2] == 'E' || strncmp (&arg[2], "export", 6) == 0)
1080                 export_flag = 1;
1081               else if (arg[2] == '6' && arg[3] == '4')
1082                 aix64_flag = 1;
1083               break;
1084 #endif
1085
1086             case 'd':
1087               if (!strcmp (arg, "-debug"))
1088                 {
1089                   /* Already parsed.  */
1090                   ld1--;
1091                   ld2--;
1092                 }
1093               break;
1094
1095             case 'l':
1096               if (first_file)
1097                 {
1098                   /* place o_file BEFORE this argument! */
1099                   first_file = 0;
1100                   ld2--;
1101                   *ld2++ = o_file;
1102                   *ld2++ = arg;
1103                 }
1104 #ifdef COLLECT_EXPORT_LIST
1105               {
1106                 /* Resolving full library name.  */
1107                 const char *s = resolve_lib_name (arg+2);
1108
1109                 /* Saving a full library name.  */
1110                 add_to_list (&libs, s);
1111               }
1112 #endif
1113               break;
1114
1115 #ifdef COLLECT_EXPORT_LIST
1116             /* Saving directories where to search for libraries.  */
1117             case 'L':
1118               add_prefix (&cmdline_lib_dirs, arg+2);
1119               break;
1120 #else
1121 #if LINK_ELIMINATE_DUPLICATE_LDIRECTORIES
1122             case 'L':
1123               if (is_in_args (arg, (const char **) ld1_argv, ld1-1))
1124                 --ld1;
1125               break;
1126 #endif /* LINK_ELIMINATE_DUPLICATE_LDIRECTORIES */
1127 #endif
1128
1129             case 'o':
1130               if (arg[2] == '\0')
1131                 output_file = *ld1++ = *ld2++ = *++argv;
1132               else if (1
1133 #ifdef SWITCHES_NEED_SPACES
1134                        && ! strchr (SWITCHES_NEED_SPACES, arg[1])
1135 #endif
1136                        )
1137
1138                 output_file = &arg[2];
1139               break;
1140
1141             case 'r':
1142               if (arg[2] == '\0')
1143                 rflag = 1;
1144               break;
1145
1146             case 's':
1147               if (arg[2] == '\0' && do_collecting)
1148                 {
1149                   /* We must strip after the nm run, otherwise C++ linking
1150                      will not work.  Thus we strip in the second ld run, or
1151                      else with strip if there is no second ld run.  */
1152                   strip_flag = 1;
1153                   ld1--;
1154                 }
1155               break;
1156
1157             case 'v':
1158               if (arg[2] == '\0')
1159                 vflag = 1;
1160               break;
1161             }
1162         }
1163       else if ((p = strrchr (arg, '.')) != (char *) 0
1164                && (strcmp (p, ".o") == 0 || strcmp (p, ".a") == 0
1165                    || strcmp (p, ".so") == 0 || strcmp (p, ".lo") == 0
1166                    || strcmp (p, ".obj") == 0))
1167         {
1168           if (first_file)
1169             {
1170               first_file = 0;
1171               if (p[1] == 'o')
1172                 *ld2++ = o_file;
1173               else
1174                 {
1175                   /* place o_file BEFORE this argument! */
1176                   ld2--;
1177                   *ld2++ = o_file;
1178                   *ld2++ = arg;
1179                 }
1180             }
1181           if (p[1] == 'o' || p[1] == 'l')
1182             *object++ = arg;
1183 #ifdef COLLECT_EXPORT_LIST
1184           /* libraries can be specified directly, i.e. without -l flag.  */
1185           else
1186             {
1187               /* Saving a full library name.  */
1188               add_to_list (&libs, arg);
1189             }
1190 #endif
1191         }
1192     }
1193
1194 #ifdef COLLECT_EXPORT_LIST
1195   /* This is added only for debugging purposes.  */
1196   if (debug)
1197     {
1198       fprintf (stderr, "List of libraries:\n");
1199       dump_list (stderr, "\t", libs.first);
1200     }
1201
1202   /* The AIX linker will discard static constructors in object files if
1203      nothing else in the file is referenced, so look at them first.  */
1204   {
1205       const char **export_object_lst = (const char **)object_lst;
1206
1207       while (export_object_lst < object)
1208         scan_prog_file (*export_object_lst++, PASS_OBJ);
1209   }
1210   {
1211     struct id *list = libs.first;
1212
1213     for (; list; list = list->next)
1214       scan_prog_file (list->name, PASS_FIRST);
1215   }
1216
1217   if (exports.first)
1218     {
1219       char *buf = concat ("-bE:", export_file, NULL);
1220
1221       *ld1++ = buf;
1222       *ld2++ = buf;
1223
1224       exportf = fopen (export_file, "w");
1225       if (exportf == (FILE *) 0)
1226         fatal_perror ("fopen %s", export_file);
1227       write_aix_file (exportf, exports.first);
1228       if (fclose (exportf))
1229         fatal_perror ("fclose %s", export_file);
1230     }
1231 #endif
1232
1233   *c_ptr++ = c_file;
1234   *c_ptr = *ld1 = *object = (char *) 0;
1235
1236   if (vflag)
1237     {
1238       notice ("collect2 version %s", version_string);
1239 #ifdef TARGET_VERSION
1240       TARGET_VERSION;
1241 #endif
1242       fprintf (stderr, "\n");
1243     }
1244
1245   if (debug)
1246     {
1247       const char *ptr;
1248       fprintf (stderr, "ld_file_name        = %s\n",
1249                (ld_file_name ? ld_file_name : "not found"));
1250       fprintf (stderr, "c_file_name         = %s\n",
1251                (c_file_name ? c_file_name : "not found"));
1252       fprintf (stderr, "nm_file_name        = %s\n",
1253                (nm_file_name ? nm_file_name : "not found"));
1254 #ifdef LDD_SUFFIX
1255       fprintf (stderr, "ldd_file_name       = %s\n",
1256                (ldd_file_name ? ldd_file_name : "not found"));
1257 #endif
1258       fprintf (stderr, "strip_file_name     = %s\n",
1259                (strip_file_name ? strip_file_name : "not found"));
1260       fprintf (stderr, "c_file              = %s\n",
1261                (c_file ? c_file : "not found"));
1262       fprintf (stderr, "o_file              = %s\n",
1263                (o_file ? o_file : "not found"));
1264
1265       ptr = getenv ("COLLECT_GCC_OPTIONS");
1266       if (ptr)
1267         fprintf (stderr, "COLLECT_GCC_OPTIONS = %s\n", ptr);
1268
1269       ptr = getenv ("COLLECT_GCC");
1270       if (ptr)
1271         fprintf (stderr, "COLLECT_GCC         = %s\n", ptr);
1272
1273       ptr = getenv ("COMPILER_PATH");
1274       if (ptr)
1275         fprintf (stderr, "COMPILER_PATH       = %s\n", ptr);
1276
1277       ptr = getenv (LIBRARY_PATH_ENV);
1278       if (ptr)
1279         fprintf (stderr, "%-20s= %s\n", LIBRARY_PATH_ENV, ptr);
1280
1281       fprintf (stderr, "\n");
1282     }
1283
1284   /* Load the program, searching all libraries and attempting to provide
1285      undefined symbols from repository information.  */
1286
1287   /* On AIX we do this later.  */
1288 #ifndef COLLECT_EXPORT_LIST
1289   do_tlink (ld1_argv, object_lst);
1290 #endif
1291
1292   /* If -r or they will be run via some other method, do not build the
1293      constructor or destructor list, just return now.  */
1294   if (rflag
1295 #ifndef COLLECT_EXPORT_LIST
1296       || ! do_collecting
1297 #endif
1298       )
1299     {
1300 #ifdef COLLECT_EXPORT_LIST
1301       /* Do the link we avoided above if we are exiting.  */
1302       do_tlink (ld1_argv, object_lst);
1303
1304       /* But make sure we delete the export file we may have created.  */
1305       if (export_file != 0 && export_file[0])
1306         maybe_unlink (export_file);
1307 #endif
1308       maybe_unlink (c_file);
1309       maybe_unlink (o_file);
1310       return 0;
1311     }
1312
1313   /* Examine the namelist with nm and search it for static constructors
1314      and destructors to call.
1315      Write the constructor and destructor tables to a .s file and reload.  */
1316
1317   /* On AIX we already scanned for global constructors/destructors.  */
1318 #ifndef COLLECT_EXPORT_LIST
1319   scan_prog_file (output_file, PASS_FIRST);
1320 #endif
1321
1322 #ifdef SCAN_LIBRARIES
1323   scan_libraries (output_file);
1324 #endif
1325
1326   if (debug)
1327     {
1328       notice ("%d constructor(s) found\n", constructors.number);
1329       notice ("%d destructor(s)  found\n", destructors.number);
1330       notice ("%d frame table(s) found\n", frame_tables.number);
1331     }
1332
1333   if (constructors.number == 0 && destructors.number == 0
1334       && frame_tables.number == 0
1335 #if defined (SCAN_LIBRARIES) || defined (COLLECT_EXPORT_LIST)
1336       /* If we will be running these functions ourselves, we want to emit
1337          stubs into the shared library so that we do not have to relink
1338          dependent programs when we add static objects.  */
1339       && ! shared_obj
1340 #endif
1341       )
1342     {
1343 #ifdef COLLECT_EXPORT_LIST
1344       /* Do tlink without additional code generation.  */
1345       do_tlink (ld1_argv, object_lst);
1346 #endif
1347       /* Strip now if it was requested on the command line.  */
1348       if (strip_flag)
1349         {
1350           char **real_strip_argv = xcalloc (sizeof (char *), 3);
1351           const char ** strip_argv = (const char **) real_strip_argv;
1352
1353           strip_argv[0] = strip_file_name;
1354           strip_argv[1] = output_file;
1355           strip_argv[2] = (char *) 0;
1356           fork_execute ("strip", real_strip_argv);
1357         }
1358
1359 #ifdef COLLECT_EXPORT_LIST
1360       maybe_unlink (export_file);
1361 #endif
1362       maybe_unlink (c_file);
1363       maybe_unlink (o_file);
1364       return 0;
1365     }
1366
1367   /* Sort ctor and dtor lists by priority.  */
1368   sort_ids (&constructors);
1369   sort_ids (&destructors);
1370
1371   maybe_unlink(output_file);
1372   outf = fopen (c_file, "w");
1373   if (outf == (FILE *) 0)
1374     fatal_perror ("fopen %s", c_file);
1375
1376   write_c_file (outf, c_file);
1377
1378   if (fclose (outf))
1379     fatal_perror ("fclose %s", c_file);
1380
1381   /* Tell the linker that we have initializer and finalizer functions.  */
1382 #ifdef LD_INIT_SWITCH
1383 #ifdef COLLECT_EXPORT_LIST
1384   *ld2++ = concat (LD_INIT_SWITCH, ":", initname, ":", fininame, NULL);
1385 #else
1386   *ld2++ = LD_INIT_SWITCH;
1387   *ld2++ = initname;
1388   *ld2++ = LD_FINI_SWITCH;
1389   *ld2++ = fininame;
1390 #endif
1391 #endif
1392
1393 #ifdef COLLECT_EXPORT_LIST
1394   if (shared_obj)
1395     {
1396       /* If we did not add export flag to link arguments before, add it to
1397          second link phase now.  No new exports should have been added.  */
1398       if (! exports.first)
1399         *ld2++ = concat ("-bE:", export_file, NULL);
1400
1401 #ifndef LD_INIT_SWITCH
1402       add_to_list (&exports, initname);
1403       add_to_list (&exports, fininame);
1404       add_to_list (&exports, "_GLOBAL__DI");
1405       add_to_list (&exports, "_GLOBAL__DD");
1406 #endif
1407       exportf = fopen (export_file, "w");
1408       if (exportf == (FILE *) 0)
1409         fatal_perror ("fopen %s", export_file);
1410       write_aix_file (exportf, exports.first);
1411       if (fclose (exportf))
1412         fatal_perror ("fclose %s", export_file);
1413     }
1414 #endif
1415
1416   /* End of arguments to second link phase.  */
1417   *ld2 = (char*) 0;
1418
1419   if (debug)
1420     {
1421       fprintf (stderr, "\n========== output_file = %s, c_file = %s\n",
1422                output_file, c_file);
1423       write_c_file (stderr, "stderr");
1424       fprintf (stderr, "========== end of c_file\n\n");
1425 #ifdef COLLECT_EXPORT_LIST
1426       fprintf (stderr, "\n========== export_file = %s\n", export_file);
1427       write_aix_file (stderr, exports.first);
1428       fprintf (stderr, "========== end of export_file\n\n");
1429 #endif
1430     }
1431
1432   /* Assemble the constructor and destructor tables.
1433      Link the tables in with the rest of the program.  */
1434
1435   fork_execute ("gcc",  c_argv);
1436 #ifdef COLLECT_EXPORT_LIST
1437   /* On AIX we must call tlink because of possible templates resolution.  */
1438   do_tlink (ld2_argv, object_lst);
1439 #else
1440   /* Otherwise, simply call ld because tlink is already done.  */
1441   fork_execute ("ld", ld2_argv);
1442
1443   /* Let scan_prog_file do any final mods (OSF/rose needs this for
1444      constructors/destructors in shared libraries.  */
1445   scan_prog_file (output_file, PASS_SECOND);
1446 #endif
1447
1448   maybe_unlink (c_file);
1449   maybe_unlink (o_file);
1450
1451 #ifdef COLLECT_EXPORT_LIST
1452   maybe_unlink (export_file);
1453 #endif
1454
1455   return 0;
1456 }
1457
1458 \f
1459 /* Wait for a process to finish, and exit if a nonzero status is found.  */
1460
1461 int
1462 collect_wait (const char *prog)
1463 {
1464   int status;
1465
1466   pwait (pid, &status, 0);
1467   if (status)
1468     {
1469       if (WIFSIGNALED (status))
1470         {
1471           int sig = WTERMSIG (status);
1472           error ("%s terminated with signal %d [%s]%s",
1473                  prog, sig, strsignal(sig),
1474                  WCOREDUMP(status) ? ", core dumped" : "");
1475           collect_exit (FATAL_EXIT_CODE);
1476         }
1477
1478       if (WIFEXITED (status))
1479         return WEXITSTATUS (status);
1480     }
1481   return 0;
1482 }
1483
1484 static void
1485 do_wait (const char *prog)
1486 {
1487   int ret = collect_wait (prog);
1488   if (ret != 0)
1489     {
1490       error ("%s returned %d exit status", prog, ret);
1491       collect_exit (ret);
1492     }
1493 }
1494
1495 \f
1496 /* Execute a program, and wait for the reply.  */
1497
1498 void
1499 collect_execute (const char *prog, char **argv, const char *redir)
1500 {
1501   char *errmsg_fmt;
1502   char *errmsg_arg;
1503   int redir_handle = -1;
1504   int stdout_save = -1;
1505   int stderr_save = -1;
1506
1507   if (vflag || debug)
1508     {
1509       char **p_argv;
1510       const char *str;
1511
1512       if (argv[0])
1513         fprintf (stderr, "%s", argv[0]);
1514       else
1515         notice ("[cannot find %s]", prog);
1516
1517       for (p_argv = &argv[1]; (str = *p_argv) != (char *) 0; p_argv++)
1518         fprintf (stderr, " %s", str);
1519
1520       fprintf (stderr, "\n");
1521     }
1522
1523   fflush (stdout);
1524   fflush (stderr);
1525
1526   /* If we cannot find a program we need, complain error.  Do this here
1527      since we might not end up needing something that we could not find.  */
1528
1529   if (argv[0] == 0)
1530     fatal ("cannot find `%s'", prog);
1531
1532   if (redir)
1533     {
1534       /* Open response file.  */
1535       redir_handle = open (redir, O_WRONLY | O_TRUNC | O_CREAT);
1536
1537       /* Duplicate the stdout and stderr file handles
1538          so they can be restored later.  */
1539       stdout_save = dup (STDOUT_FILENO);
1540       if (stdout_save == -1)
1541         fatal_perror ("redirecting stdout: %s", redir);
1542       stderr_save = dup (STDERR_FILENO);
1543       if (stderr_save == -1)
1544         fatal_perror ("redirecting stdout: %s", redir);
1545
1546       /* Redirect stdout & stderr to our response file.  */
1547       dup2 (redir_handle, STDOUT_FILENO);
1548       dup2 (redir_handle, STDERR_FILENO);
1549     }
1550
1551   pid = pexecute (argv[0], argv, argv[0], NULL, &errmsg_fmt, &errmsg_arg,
1552                   (PEXECUTE_FIRST | PEXECUTE_LAST | PEXECUTE_SEARCH));
1553
1554   if (redir)
1555     {
1556       /* Restore stdout and stderr to their previous settings.  */
1557       dup2 (stdout_save, STDOUT_FILENO);
1558       dup2 (stderr_save, STDERR_FILENO);
1559
1560       /* Close response file.  */
1561       close (redir_handle);
1562     }
1563
1564  if (pid == -1)
1565    fatal_perror (errmsg_fmt, errmsg_arg);
1566 }
1567
1568 static void
1569 fork_execute (const char *prog, char **argv)
1570 {
1571   collect_execute (prog, argv, NULL);
1572   do_wait (prog);
1573 }
1574 \f
1575 /* Unlink a file unless we are debugging.  */
1576
1577 static void
1578 maybe_unlink (const char *file)
1579 {
1580   if (!debug)
1581     unlink (file);
1582   else
1583     notice ("[Leaving %s]\n", file);
1584 }
1585
1586 \f
1587 static long sequence_number = 0;
1588
1589 /* Add a name to a linked list.  */
1590
1591 static void
1592 add_to_list (struct head *head_ptr, const char *name)
1593 {
1594   struct id *newid = xcalloc (sizeof (struct id) + strlen (name), 1);
1595   struct id *p;
1596   strcpy (newid->name, name);
1597
1598   if (head_ptr->first)
1599     head_ptr->last->next = newid;
1600   else
1601     head_ptr->first = newid;
1602
1603   /* Check for duplicate symbols.  */
1604   for (p = head_ptr->first;
1605        strcmp (name, p->name) != 0;
1606        p = p->next)
1607     ;
1608   if (p != newid)
1609     {
1610       head_ptr->last->next = 0;
1611       free (newid);
1612       return;
1613     }
1614
1615   newid->sequence = ++sequence_number;
1616   head_ptr->last = newid;
1617   head_ptr->number++;
1618 }
1619
1620 /* Grab the init priority number from an init function name that
1621    looks like "_GLOBAL_.I.12345.foo".  */
1622
1623 static int
1624 extract_init_priority (const char *name)
1625 {
1626   int pos = 0, pri;
1627
1628   while (name[pos] == '_')
1629     ++pos;
1630   pos += 10; /* strlen ("GLOBAL__X_") */
1631
1632   /* Extract init_p number from ctor/dtor name.  */
1633   pri = atoi (name + pos);
1634   return pri ? pri : DEFAULT_INIT_PRIORITY;
1635 }
1636
1637 /* Insertion sort the ids from ctor/dtor list HEAD_PTR in descending order.
1638    ctors will be run from right to left, dtors from left to right.  */
1639
1640 static void
1641 sort_ids (struct head *head_ptr)
1642 {
1643   /* id holds the current element to insert.  id_next holds the next
1644      element to insert.  id_ptr iterates through the already sorted elements
1645      looking for the place to insert id.  */
1646   struct id *id, *id_next, **id_ptr;
1647
1648   id = head_ptr->first;
1649
1650   /* We don't have any sorted elements yet.  */
1651   head_ptr->first = NULL;
1652
1653   for (; id; id = id_next)
1654     {
1655       id_next = id->next;
1656       id->sequence = extract_init_priority (id->name);
1657
1658       for (id_ptr = &(head_ptr->first); ; id_ptr = &((*id_ptr)->next))
1659         if (*id_ptr == NULL
1660             /* If the sequence numbers are the same, we put the id from the
1661                file later on the command line later in the list.  */
1662             || id->sequence > (*id_ptr)->sequence
1663             /* Hack: do lexical compare, too.
1664             || (id->sequence == (*id_ptr)->sequence
1665                 && strcmp (id->name, (*id_ptr)->name) > 0) */
1666             )
1667           {
1668             id->next = *id_ptr;
1669             *id_ptr = id;
1670             break;
1671           }
1672     }
1673
1674   /* Now set the sequence numbers properly so write_c_file works.  */
1675   for (id = head_ptr->first; id; id = id->next)
1676     id->sequence = ++sequence_number;
1677 }
1678
1679 /* Write: `prefix', the names on list LIST, `suffix'.  */
1680
1681 static void
1682 write_list (FILE *stream, const char *prefix, struct id *list)
1683 {
1684   while (list)
1685     {
1686       fprintf (stream, "%sx%d,\n", prefix, list->sequence);
1687       list = list->next;
1688     }
1689 }
1690
1691 #if LINK_ELIMINATE_DUPLICATE_LDIRECTORIES
1692 /* Given a STRING, return nonzero if it occurs in the list in range
1693    [ARGS_BEGIN,ARGS_END).  */
1694
1695 static int
1696 is_in_args (const char *string, const char **args_begin,
1697             const char **args_end)
1698 {
1699   const char **args_pointer;
1700   for (args_pointer = args_begin; args_pointer != args_end; ++args_pointer)
1701     if (strcmp (string, *args_pointer) == 0)
1702       return 1;
1703   return 0;
1704 }
1705 #endif /* LINK_ELIMINATE_DUPLICATE_LDIRECTORIES */
1706
1707 #ifdef COLLECT_EXPORT_LIST
1708 /* This function is really used only on AIX, but may be useful.  */
1709 #if 0
1710 static int
1711 is_in_list (const char *prefix, struct id *list)
1712 {
1713   while (list)
1714     {
1715       if (!strcmp (prefix, list->name)) return 1;
1716       list = list->next;
1717     }
1718     return 0;
1719 }
1720 #endif
1721 #endif /* COLLECT_EXPORT_LIST */
1722
1723 /* Added for debugging purpose.  */
1724 #ifdef COLLECT_EXPORT_LIST
1725 static void
1726 dump_list (FILE *stream, const char *prefix, struct id *list)
1727 {
1728   while (list)
1729     {
1730       fprintf (stream, "%s%s,\n", prefix, list->name);
1731       list = list->next;
1732     }
1733 }
1734 #endif
1735
1736 #if 0
1737 static void
1738 dump_prefix_list (FILE *stream, const char *prefix, struct prefix_list *list)
1739 {
1740   while (list)
1741     {
1742       fprintf (stream, "%s%s,\n", prefix, list->prefix);
1743       list = list->next;
1744     }
1745 }
1746 #endif
1747
1748 static void
1749 write_list_with_asm (FILE *stream, const char *prefix, struct id *list)
1750 {
1751   while (list)
1752     {
1753       fprintf (stream, "%sx%d __asm__ (\"%s\");\n",
1754                prefix, list->sequence, list->name);
1755       list = list->next;
1756     }
1757 }
1758
1759 /* Write out the constructor and destructor tables statically (for a shared
1760    object), along with the functions to execute them.  */
1761
1762 static void
1763 write_c_file_stat (FILE *stream, const char *name ATTRIBUTE_UNUSED)
1764 {
1765   const char *p, *q;
1766   char *prefix, *r;
1767   int frames = (frame_tables.number > 0);
1768
1769   /* Figure out name of output_file, stripping off .so version.  */
1770   p = strrchr (output_file, '/');
1771   if (p == 0)
1772     p = output_file;
1773   else
1774     p++;
1775   q = p;
1776   while (q)
1777     {
1778       q = strchr (q,'.');
1779       if (q == 0)
1780         {
1781           q = p + strlen (p);
1782           break;
1783         }
1784       else
1785         {
1786           if (strncmp (q, ".so", 3) == 0)
1787             {
1788               q += 3;
1789               break;
1790             }
1791           else
1792             q++;
1793         }
1794     }
1795   /* q points to null at end of the string (or . of the .so version) */
1796   prefix = xmalloc (q - p + 1);
1797   strncpy (prefix, p, q - p);
1798   prefix[q - p] = 0;
1799   for (r = prefix; *r; r++)
1800     if (!ISALNUM ((unsigned char)*r))
1801       *r = '_';
1802   if (debug)
1803     notice ("\nwrite_c_file - output name is %s, prefix is %s\n",
1804             output_file, prefix);
1805
1806   initname = concat ("_GLOBAL__FI_", prefix, NULL);
1807   fininame = concat ("_GLOBAL__FD_", prefix, NULL);
1808
1809   free (prefix);
1810
1811   /* Write the tables as C code.  */
1812
1813   fprintf (stream, "static int count;\n");
1814   fprintf (stream, "typedef void entry_pt();\n");
1815   write_list_with_asm (stream, "extern entry_pt ", constructors.first);
1816
1817   if (frames)
1818     {
1819       write_list_with_asm (stream, "extern void *", frame_tables.first);
1820
1821       fprintf (stream, "\tstatic void *frame_table[] = {\n");
1822       write_list (stream, "\t\t&", frame_tables.first);
1823       fprintf (stream, "\t0\n};\n");
1824
1825       /* This must match what's in frame.h.  */
1826       fprintf (stream, "struct object {\n");
1827       fprintf (stream, "  void *pc_begin;\n");
1828       fprintf (stream, "  void *pc_end;\n");
1829       fprintf (stream, "  void *fde_begin;\n");
1830       fprintf (stream, "  void *fde_array;\n");
1831       fprintf (stream, "  __SIZE_TYPE__ count;\n");
1832       fprintf (stream, "  struct object *next;\n");
1833       fprintf (stream, "};\n");
1834
1835       fprintf (stream, "extern void __register_frame_info_table (void *, struct object *);\n");
1836       fprintf (stream, "extern void *__deregister_frame_info (void *);\n");
1837
1838       fprintf (stream, "static void reg_frame () {\n");
1839       fprintf (stream, "\tstatic struct object ob;\n");
1840       fprintf (stream, "\t__register_frame_info_table (frame_table, &ob);\n");
1841       fprintf (stream, "\t}\n");
1842
1843       fprintf (stream, "static void dereg_frame () {\n");
1844       fprintf (stream, "\t__deregister_frame_info (frame_table);\n");
1845       fprintf (stream, "\t}\n");
1846     }
1847
1848   fprintf (stream, "void %s() {\n", initname);
1849   if (constructors.number > 0 || frames)
1850     {
1851       fprintf (stream, "\tstatic entry_pt *ctors[] = {\n");
1852       write_list (stream, "\t\t", constructors.first);
1853       if (frames)
1854         fprintf (stream, "\treg_frame,\n");
1855       fprintf (stream, "\t};\n");
1856       fprintf (stream, "\tentry_pt **p;\n");
1857       fprintf (stream, "\tif (count++ != 0) return;\n");
1858       fprintf (stream, "\tp = ctors + %d;\n", constructors.number + frames);
1859       fprintf (stream, "\twhile (p > ctors) (*--p)();\n");
1860     }
1861   else
1862     fprintf (stream, "\t++count;\n");
1863   fprintf (stream, "}\n");
1864   write_list_with_asm (stream, "extern entry_pt ", destructors.first);
1865   fprintf (stream, "void %s() {\n", fininame);
1866   if (destructors.number > 0 || frames)
1867     {
1868       fprintf (stream, "\tstatic entry_pt *dtors[] = {\n");
1869       write_list (stream, "\t\t", destructors.first);
1870       if (frames)
1871         fprintf (stream, "\tdereg_frame,\n");
1872       fprintf (stream, "\t};\n");
1873       fprintf (stream, "\tentry_pt **p;\n");
1874       fprintf (stream, "\tif (--count != 0) return;\n");
1875       fprintf (stream, "\tp = dtors;\n");
1876       fprintf (stream, "\twhile (p < dtors + %d) (*p++)();\n",
1877                destructors.number + frames);
1878     }
1879   fprintf (stream, "}\n");
1880
1881   if (shared_obj)
1882     {
1883       COLLECT_SHARED_INIT_FUNC(stream, initname);
1884       COLLECT_SHARED_FINI_FUNC(stream, fininame);
1885     }
1886 }
1887
1888 /* Write the constructor/destructor tables.  */
1889
1890 #ifndef LD_INIT_SWITCH
1891 static void
1892 write_c_file_glob (FILE *stream, const char *name ATTRIBUTE_UNUSED)
1893 {
1894   /* Write the tables as C code.  */
1895
1896   int frames = (frame_tables.number > 0);
1897
1898   fprintf (stream, "typedef void entry_pt();\n\n");
1899
1900   write_list_with_asm (stream, "extern entry_pt ", constructors.first);
1901
1902   if (frames)
1903     {
1904       write_list_with_asm (stream, "extern void *", frame_tables.first);
1905
1906       fprintf (stream, "\tstatic void *frame_table[] = {\n");
1907       write_list (stream, "\t\t&", frame_tables.first);
1908       fprintf (stream, "\t0\n};\n");
1909
1910       /* This must match what's in frame.h.  */
1911       fprintf (stream, "struct object {\n");
1912       fprintf (stream, "  void *pc_begin;\n");
1913       fprintf (stream, "  void *pc_end;\n");
1914       fprintf (stream, "  void *fde_begin;\n");
1915       fprintf (stream, "  void *fde_array;\n");
1916       fprintf (stream, "  __SIZE_TYPE__ count;\n");
1917       fprintf (stream, "  struct object *next;\n");
1918       fprintf (stream, "};\n");
1919
1920       fprintf (stream, "extern void __register_frame_info_table (void *, struct object *);\n");
1921       fprintf (stream, "extern void *__deregister_frame_info (void *);\n");
1922
1923       fprintf (stream, "static void reg_frame () {\n");
1924       fprintf (stream, "\tstatic struct object ob;\n");
1925       fprintf (stream, "\t__register_frame_info_table (frame_table, &ob);\n");
1926       fprintf (stream, "\t}\n");
1927
1928       fprintf (stream, "static void dereg_frame () {\n");
1929       fprintf (stream, "\t__deregister_frame_info (frame_table);\n");
1930       fprintf (stream, "\t}\n");
1931     }
1932
1933   fprintf (stream, "\nentry_pt * __CTOR_LIST__[] = {\n");
1934   fprintf (stream, "\t(entry_pt *) %d,\n", constructors.number + frames);
1935   write_list (stream, "\t", constructors.first);
1936   if (frames)
1937     fprintf (stream, "\treg_frame,\n");
1938   fprintf (stream, "\t0\n};\n\n");
1939
1940   write_list_with_asm (stream, "extern entry_pt ", destructors.first);
1941
1942   fprintf (stream, "\nentry_pt * __DTOR_LIST__[] = {\n");
1943   fprintf (stream, "\t(entry_pt *) %d,\n", destructors.number + frames);
1944   write_list (stream, "\t", destructors.first);
1945   if (frames)
1946     fprintf (stream, "\tdereg_frame,\n");
1947   fprintf (stream, "\t0\n};\n\n");
1948
1949   fprintf (stream, "extern entry_pt %s;\n", NAME__MAIN);
1950   fprintf (stream, "entry_pt *__main_reference = %s;\n\n", NAME__MAIN);
1951 }
1952 #endif /* ! LD_INIT_SWITCH */
1953
1954 static void
1955 write_c_file (FILE *stream, const char *name)
1956 {
1957   fprintf (stream, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n");
1958 #ifndef LD_INIT_SWITCH
1959   if (! shared_obj)
1960     write_c_file_glob (stream, name);
1961   else
1962 #endif
1963     write_c_file_stat (stream, name);
1964   fprintf (stream, "#ifdef __cplusplus\n}\n#endif\n");
1965 }
1966
1967 #ifdef COLLECT_EXPORT_LIST
1968 static void
1969 write_aix_file (FILE *stream, struct id *list)
1970 {
1971   for (; list; list = list->next)
1972     {
1973       fputs (list->name, stream);
1974       putc ('\n', stream);
1975     }
1976 }
1977 #endif
1978 \f
1979 #ifdef OBJECT_FORMAT_NONE
1980
1981 /* Generic version to scan the name list of the loaded program for
1982    the symbols g++ uses for static constructors and destructors.
1983
1984    The constructor table begins at __CTOR_LIST__ and contains a count
1985    of the number of pointers (or -1 if the constructors are built in a
1986    separate section by the linker), followed by the pointers to the
1987    constructor functions, terminated with a null pointer.  The
1988    destructor table has the same format, and begins at __DTOR_LIST__.  */
1989
1990 static void
1991 scan_prog_file (const char *prog_name, enum pass which_pass)
1992 {
1993   void (*int_handler) (int);
1994   void (*quit_handler) (int);
1995   char *real_nm_argv[4];
1996   const char **nm_argv = (const char **) real_nm_argv;
1997   int argc = 0;
1998   int pipe_fd[2];
1999   char *p, buf[1024];
2000   FILE *inf;
2001
2002   if (which_pass == PASS_SECOND)
2003     return;
2004
2005   /* If we do not have an `nm', complain.  */
2006   if (nm_file_name == 0)
2007     fatal ("cannot find `nm'");
2008
2009   nm_argv[argc++] = nm_file_name;
2010   if (NM_FLAGS[0] != '\0')
2011     nm_argv[argc++] = NM_FLAGS;
2012
2013   nm_argv[argc++] = prog_name;
2014   nm_argv[argc++] = (char *) 0;
2015
2016   if (pipe (pipe_fd) < 0)
2017     fatal_perror ("pipe");
2018
2019   inf = fdopen (pipe_fd[0], "r");
2020   if (inf == (FILE *) 0)
2021     fatal_perror ("fdopen");
2022
2023   /* Trace if needed.  */
2024   if (vflag)
2025     {
2026       const char **p_argv;
2027       const char *str;
2028
2029       for (p_argv = &nm_argv[0]; (str = *p_argv) != (char *) 0; p_argv++)
2030         fprintf (stderr, " %s", str);
2031
2032       fprintf (stderr, "\n");
2033     }
2034
2035   fflush (stdout);
2036   fflush (stderr);
2037
2038   /* Spawn child nm on pipe.  */
2039   pid = vfork ();
2040   if (pid == -1)
2041     fatal_perror (VFORK_STRING);
2042
2043   if (pid == 0)                 /* child context */
2044     {
2045       /* setup stdout */
2046       if (dup2 (pipe_fd[1], 1) < 0)
2047         fatal_perror ("dup2 %d 1", pipe_fd[1]);
2048
2049       if (close (pipe_fd[0]) < 0)
2050         fatal_perror ("close %d", pipe_fd[0]);
2051
2052       if (close (pipe_fd[1]) < 0)
2053         fatal_perror ("close %d", pipe_fd[1]);
2054
2055       execv (nm_file_name, real_nm_argv);
2056       fatal_perror ("execv %s", nm_file_name);
2057     }
2058
2059   /* Parent context from here on.  */
2060   int_handler  = (void (*) (int)) signal (SIGINT,  SIG_IGN);
2061 #ifdef SIGQUIT
2062   quit_handler = (void (*) (int)) signal (SIGQUIT, SIG_IGN);
2063 #endif
2064
2065   if (close (pipe_fd[1]) < 0)
2066     fatal_perror ("close %d", pipe_fd[1]);
2067
2068   if (debug)
2069     fprintf (stderr, "\nnm output with constructors/destructors.\n");
2070
2071   /* Read each line of nm output.  */
2072   while (fgets (buf, sizeof buf, inf) != (char *) 0)
2073     {
2074       int ch, ch2;
2075       char *name, *end;
2076
2077       /* If it contains a constructor or destructor name, add the name
2078          to the appropriate list.  */
2079
2080       for (p = buf; (ch = *p) != '\0' && ch != '\n' && ch != '_'; p++)
2081         if (ch == ' ' && p[1] == 'U' && p[2] == ' ')
2082           break;
2083
2084       if (ch != '_')
2085         continue;
2086
2087       name = p;
2088       /* Find the end of the symbol name.
2089          Do not include `|', because Encore nm can tack that on the end.  */
2090       for (end = p; (ch2 = *end) != '\0' && !ISSPACE (ch2) && ch2 != '|';
2091            end++)
2092         continue;
2093
2094
2095       *end = '\0';
2096       switch (is_ctor_dtor (name))
2097         {
2098         case 1:
2099           if (which_pass != PASS_LIB)
2100             add_to_list (&constructors, name);
2101           break;
2102
2103         case 2:
2104           if (which_pass != PASS_LIB)
2105             add_to_list (&destructors, name);
2106           break;
2107
2108         case 3:
2109           if (which_pass != PASS_LIB)
2110             fatal ("init function found in object %s", prog_name);
2111 #ifndef LD_INIT_SWITCH
2112           add_to_list (&constructors, name);
2113 #endif
2114           break;
2115
2116         case 4:
2117           if (which_pass != PASS_LIB)
2118             fatal ("fini function found in object %s", prog_name);
2119 #ifndef LD_FINI_SWITCH
2120           add_to_list (&destructors, name);
2121 #endif
2122           break;
2123
2124         case 5:
2125           if (which_pass != PASS_LIB)
2126             add_to_list (&frame_tables, name);
2127           break;
2128
2129         default:                /* not a constructor or destructor */
2130           continue;
2131         }
2132
2133       if (debug)
2134         fprintf (stderr, "\t%s\n", buf);
2135     }
2136
2137   if (debug)
2138     fprintf (stderr, "\n");
2139
2140   if (fclose (inf) != 0)
2141     fatal_perror ("fclose");
2142
2143   do_wait (nm_file_name);
2144
2145   signal (SIGINT,  int_handler);
2146 #ifdef SIGQUIT
2147   signal (SIGQUIT, quit_handler);
2148 #endif
2149 }
2150
2151 #if SUNOS4_SHARED_LIBRARIES
2152
2153 /* Routines to scan the SunOS 4 _DYNAMIC structure to find shared libraries
2154    that the output file depends upon and their initialization/finalization
2155    routines, if any.  */
2156
2157 #include <a.out.h>
2158 #include <fcntl.h>
2159 #include <link.h>
2160 #include <sys/mman.h>
2161 #include <sys/param.h>
2162 #include <unistd.h>
2163 #include <sys/dir.h>
2164
2165 /* pointers to the object file */
2166 unsigned object;        /* address of memory mapped file */
2167 unsigned objsize;       /* size of memory mapped to file */
2168 char * code;            /* pointer to code segment */
2169 char * data;            /* pointer to data segment */
2170 struct nlist *symtab;   /* pointer to symbol table */
2171 struct link_dynamic *ld;
2172 struct link_dynamic_2 *ld_2;
2173 struct head libraries;
2174
2175 /* Map the file indicated by NAME into memory and store its address.  */
2176
2177 static void
2178 mapfile (const char *name)
2179 {
2180   int fp;
2181   struct stat s;
2182   if ((fp = open (name, O_RDONLY)) == -1)
2183     fatal ("unable to open file '%s'", name);
2184   if (fstat (fp, &s) == -1)
2185     fatal ("unable to stat file '%s'", name);
2186
2187   objsize = s.st_size;
2188   object = (unsigned) mmap (0, objsize, PROT_READ|PROT_WRITE, MAP_PRIVATE,
2189                             fp, 0);
2190   if (object == (unsigned)-1)
2191     fatal ("unable to mmap file '%s'", name);
2192
2193   close (fp);
2194 }
2195
2196 /* Helpers for locatelib.  */
2197
2198 static const char *libname;
2199
2200 static int
2201 libselect (struct direct *d)
2202 {
2203   return (strncmp (libname, d->d_name, strlen (libname)) == 0);
2204 }
2205
2206 /* If one file has an additional numeric extension past LIBNAME, then put
2207    that one first in the sort.  If both files have additional numeric
2208    extensions, then put the one with the higher number first in the sort.
2209
2210    We must verify that the extension is numeric, because Sun saves the
2211    original versions of patched libraries with a .FCS extension.  Files with
2212    invalid extensions must go last in the sort, so that they will not be used.  */
2213
2214 static int
2215 libcompare (struct direct **d1, struct direct **d2)
2216 {
2217   int i1, i2 = strlen (libname);
2218   char *e1 = (*d1)->d_name + i2;
2219   char *e2 = (*d2)->d_name + i2;
2220
2221   while (*e1 && *e2 && *e1 == '.' && *e2 == '.'
2222          && e1[1] && ISDIGIT (e1[1]) && e2[1] && ISDIGIT (e2[1]))
2223     {
2224       ++e1;
2225       ++e2;
2226       i1 = strtol (e1, &e1, 10);
2227       i2 = strtol (e2, &e2, 10);
2228       if (i1 != i2)
2229         return i1 - i2;
2230     }
2231
2232   if (*e1)
2233     {
2234       /* It has a valid numeric extension, prefer this one.  */
2235       if (*e1 == '.' && e1[1] && ISDIGIT (e1[1]))
2236         return 1;
2237       /* It has an invalid numeric extension, must prefer the other one.  */
2238       else
2239         return -1;
2240     }
2241   else if (*e2)
2242     {
2243       /* It has a valid numeric extension, prefer this one.  */
2244       if (*e2 == '.' && e2[1] && ISDIGIT (e2[1]))
2245         return -1;
2246       /* It has an invalid numeric extension, must prefer the other one.  */
2247       else
2248         return 1;
2249     }
2250   else
2251     return 0;
2252 }
2253
2254 /* Given the name NAME of a dynamic dependency, find its pathname and add
2255    it to the list of libraries.  */
2256
2257 static void
2258 locatelib (const char *name)
2259 {
2260   static const char **l;
2261   static int cnt;
2262   char buf[MAXPATHLEN];
2263   char *p, *q;
2264   const char **pp;
2265
2266   if (l == 0)
2267     {
2268       char *ld_rules;
2269       char *ldr = 0;
2270       /* counting elements in array, need 1 extra for null */
2271       cnt = 1;
2272       ld_rules = (char *) (ld_2->ld_rules + code);
2273       if (ld_rules)
2274         {
2275           cnt++;
2276           for (; *ld_rules != 0; ld_rules++)
2277             if (*ld_rules == ':')
2278               cnt++;
2279           ld_rules = (char *) (ld_2->ld_rules + code);
2280           ldr = xstrdup (ld_rules);
2281         }
2282       p = getenv ("LD_LIBRARY_PATH");
2283       q = 0;
2284       if (p)
2285         {
2286           cnt++;
2287           for (q = p ; *q != 0; q++)
2288             if (*q == ':')
2289               cnt++;
2290           q = xstrdup (p);
2291         }
2292       l = xmalloc ((cnt + 3) * sizeof (char *));
2293       pp = l;
2294       if (ldr)
2295         {
2296           *pp++ = ldr;
2297           for (; *ldr != 0; ldr++)
2298             if (*ldr == ':')
2299               {
2300                 *ldr++ = 0;
2301                 *pp++ = ldr;
2302               }
2303         }
2304       if (q)
2305         {
2306           *pp++ = q;
2307           for (; *q != 0; q++)
2308             if (*q == ':')
2309               {
2310                 *q++ = 0;
2311                 *pp++ = q;
2312               }
2313         }
2314       /* built in directories are /lib, /usr/lib, and /usr/local/lib */
2315       *pp++ = "/lib";
2316       *pp++ = "/usr/lib";
2317       *pp++ = "/usr/local/lib";
2318       *pp = 0;
2319     }
2320   libname = name;
2321   for (pp = l; *pp != 0 ; pp++)
2322     {
2323       struct direct **namelist;
2324       int entries;
2325       if ((entries = scandir (*pp, &namelist, libselect, libcompare)) > 0)
2326         {
2327           sprintf (buf, "%s/%s", *pp, namelist[entries - 1]->d_name);
2328           add_to_list (&libraries, buf);
2329           if (debug)
2330             fprintf (stderr, "%s\n", buf);
2331           break;
2332         }
2333     }
2334   if (*pp == 0)
2335     {
2336       if (debug)
2337         notice ("not found\n");
2338       else
2339         fatal ("dynamic dependency %s not found", name);
2340     }
2341 }
2342
2343 /* Scan the _DYNAMIC structure of the output file to find shared libraries
2344    that it depends upon and any constructors or destructors they contain.  */
2345
2346 static void
2347 scan_libraries (const char *prog_name)
2348 {
2349   struct exec *header;
2350   char *base;
2351   struct link_object *lo;
2352   char buff[MAXPATHLEN];
2353   struct id *list;
2354
2355   mapfile (prog_name);
2356   header = (struct exec *)object;
2357   if (N_BADMAG (*header))
2358     fatal ("bad magic number in file '%s'", prog_name);
2359   if (header->a_dynamic == 0)
2360     return;
2361
2362   code = (char *) (N_TXTOFF (*header) + (long) header);
2363   data = (char *) (N_DATOFF (*header) + (long) header);
2364   symtab = (struct nlist *) (N_SYMOFF (*header) + (long) header);
2365
2366   if (header->a_magic == ZMAGIC && header->a_entry == 0x20)
2367     {
2368       /* shared object */
2369       ld = (struct link_dynamic *) (symtab->n_value + code);
2370       base = code;
2371     }
2372   else
2373     {
2374       /* executable */
2375       ld = (struct link_dynamic *) data;
2376       base = code-PAGSIZ;
2377     }
2378
2379   if (debug)
2380     notice ("dynamic dependencies.\n");
2381
2382   ld_2 = (struct link_dynamic_2 *) ((long) ld->ld_un.ld_2 + (long)base);
2383   for (lo = (struct link_object *) ld_2->ld_need; lo;
2384        lo = (struct link_object *) lo->lo_next)
2385     {
2386       char *name;
2387       lo = (struct link_object *) ((long) lo + code);
2388       name = (char *) (code + lo->lo_name);
2389       if (lo->lo_library)
2390         {
2391           if (debug)
2392             fprintf (stderr, "\t-l%s.%d => ", name, lo->lo_major);
2393           sprintf (buff, "lib%s.so.%d.%d", name, lo->lo_major, lo->lo_minor);
2394           locatelib (buff);
2395         }
2396       else
2397         {
2398           if (debug)
2399             fprintf (stderr, "\t%s\n", name);
2400           add_to_list (&libraries, name);
2401         }
2402     }
2403
2404   if (debug)
2405     fprintf (stderr, "\n");
2406
2407   /* Now iterate through the library list adding their symbols to
2408      the list.  */
2409   for (list = libraries.first; list; list = list->next)
2410     scan_prog_file (list->name, PASS_LIB);
2411 }
2412
2413 #else  /* SUNOS4_SHARED_LIBRARIES */
2414 #ifdef LDD_SUFFIX
2415
2416 /* Use the List Dynamic Dependencies program to find shared libraries that
2417    the output file depends upon and their initialization/finalization
2418    routines, if any.  */
2419
2420 static void
2421 scan_libraries (const char *prog_name)
2422 {
2423   static struct head libraries;         /* list of shared libraries found */
2424   struct id *list;
2425   void (*int_handler) (int);
2426   void (*quit_handler) (int);
2427   char *real_ldd_argv[4];
2428   const char **ldd_argv = (const char **) real_ldd_argv;
2429   int argc = 0;
2430   int pipe_fd[2];
2431   char buf[1024];
2432   FILE *inf;
2433
2434   /* If we do not have an `ldd', complain.  */
2435   if (ldd_file_name == 0)
2436     {
2437       error ("cannot find `ldd'");
2438       return;
2439     }
2440
2441   ldd_argv[argc++] = ldd_file_name;
2442   ldd_argv[argc++] = prog_name;
2443   ldd_argv[argc++] = (char *) 0;
2444
2445   if (pipe (pipe_fd) < 0)
2446     fatal_perror ("pipe");
2447
2448   inf = fdopen (pipe_fd[0], "r");
2449   if (inf == (FILE *) 0)
2450     fatal_perror ("fdopen");
2451
2452   /* Trace if needed.  */
2453   if (vflag)
2454     {
2455       const char **p_argv;
2456       const char *str;
2457
2458       for (p_argv = &ldd_argv[0]; (str = *p_argv) != (char *) 0; p_argv++)
2459         fprintf (stderr, " %s", str);
2460
2461       fprintf (stderr, "\n");
2462     }
2463
2464   fflush (stdout);
2465   fflush (stderr);
2466
2467   /* Spawn child ldd on pipe.  */
2468   pid = vfork ();
2469   if (pid == -1)
2470     fatal_perror (VFORK_STRING);
2471
2472   if (pid == 0)                 /* child context */
2473     {
2474       /* setup stdout */
2475       if (dup2 (pipe_fd[1], 1) < 0)
2476         fatal_perror ("dup2 %d 1", pipe_fd[1]);
2477
2478       if (close (pipe_fd[0]) < 0)
2479         fatal_perror ("close %d", pipe_fd[0]);
2480
2481       if (close (pipe_fd[1]) < 0)
2482         fatal_perror ("close %d", pipe_fd[1]);
2483
2484       execv (ldd_file_name, real_ldd_argv);
2485       fatal_perror ("execv %s", ldd_file_name);
2486     }
2487
2488   /* Parent context from here on.  */
2489   int_handler  = (void (*) (int)) signal (SIGINT,  SIG_IGN);
2490 #ifdef SIGQUIT
2491   quit_handler = (void (*) (int)) signal (SIGQUIT, SIG_IGN);
2492 #endif
2493
2494   if (close (pipe_fd[1]) < 0)
2495     fatal_perror ("close %d", pipe_fd[1]);
2496
2497   if (debug)
2498     notice ("\nldd output with constructors/destructors.\n");
2499
2500   /* Read each line of ldd output.  */
2501   while (fgets (buf, sizeof buf, inf) != (char *) 0)
2502     {
2503       int ch2;
2504       char *name, *end, *p = buf;
2505
2506       /* Extract names of libraries and add to list.  */
2507       PARSE_LDD_OUTPUT (p);
2508       if (p == 0)
2509         continue;
2510
2511       name = p;
2512       if (strncmp (name, "not found", sizeof ("not found") - 1) == 0)
2513         fatal ("dynamic dependency %s not found", buf);
2514
2515       /* Find the end of the symbol name.  */
2516       for (end = p;
2517            (ch2 = *end) != '\0' && ch2 != '\n' && !ISSPACE (ch2) && ch2 != '|';
2518            end++)
2519         continue;
2520       *end = '\0';
2521
2522       if (access (name, R_OK) == 0)
2523         add_to_list (&libraries, name);
2524       else
2525         fatal ("unable to open dynamic dependency '%s'", buf);
2526
2527       if (debug)
2528         fprintf (stderr, "\t%s\n", buf);
2529     }
2530   if (debug)
2531     fprintf (stderr, "\n");
2532
2533   if (fclose (inf) != 0)
2534     fatal_perror ("fclose");
2535
2536   do_wait (ldd_file_name);
2537
2538   signal (SIGINT,  int_handler);
2539 #ifdef SIGQUIT
2540   signal (SIGQUIT, quit_handler);
2541 #endif
2542
2543   /* Now iterate through the library list adding their symbols to
2544      the list.  */
2545   for (list = libraries.first; list; list = list->next)
2546     scan_prog_file (list->name, PASS_LIB);
2547 }
2548
2549 #endif /* LDD_SUFFIX */
2550 #endif /* SUNOS4_SHARED_LIBRARIES */
2551
2552 #endif /* OBJECT_FORMAT_NONE */
2553
2554 \f
2555 /*
2556  * COFF specific stuff.
2557  */
2558
2559 #ifdef OBJECT_FORMAT_COFF
2560
2561 #if defined (EXTENDED_COFF)
2562
2563 #   define GCC_SYMBOLS(X)       (SYMHEADER(X).isymMax + SYMHEADER(X).iextMax)
2564 #   define GCC_SYMENT           SYMR
2565 #   define GCC_OK_SYMBOL(X)     ((X).st == stProc || (X).st == stGlobal)
2566 #   define GCC_SYMINC(X)        (1)
2567 #   define GCC_SYMZERO(X)       (SYMHEADER(X).isymMax)
2568 #   define GCC_CHECK_HDR(X)     (PSYMTAB(X) != 0)
2569
2570 #else
2571
2572 #   define GCC_SYMBOLS(X)       (HEADER(ldptr).f_nsyms)
2573 #   define GCC_SYMENT           SYMENT
2574 #   if defined (C_WEAKEXT)
2575 #     define GCC_OK_SYMBOL(X) \
2576        (((X).n_sclass == C_EXT || (X).n_sclass == C_WEAKEXT) && \
2577         ((X).n_scnum > N_UNDEF) && \
2578         (aix64_flag \
2579          || (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) \
2580              || ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT))))
2581 #     define GCC_UNDEF_SYMBOL(X) \
2582        (((X).n_sclass == C_EXT || (X).n_sclass == C_WEAKEXT) && \
2583         ((X).n_scnum == N_UNDEF))
2584 #   else
2585 #     define GCC_OK_SYMBOL(X) \
2586        (((X).n_sclass == C_EXT) && \
2587         ((X).n_scnum > N_UNDEF) && \
2588         (aix64_flag \
2589          || (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) \
2590              || ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT))))
2591 #     define GCC_UNDEF_SYMBOL(X) \
2592        (((X).n_sclass == C_EXT) && ((X).n_scnum == N_UNDEF))
2593 #   endif
2594 #   define GCC_SYMINC(X)        ((X).n_numaux+1)
2595 #   define GCC_SYMZERO(X)       0
2596
2597 /* 0757 = U803XTOCMAGIC (AIX 4.3) and 0767 = U64_TOCMAGIC (AIX V5) */
2598 #ifdef _AIX51
2599 #   define GCC_CHECK_HDR(X) \
2600      ((HEADER (X).f_magic == U802TOCMAGIC && ! aix64_flag) \
2601       || (HEADER (X).f_magic == 0767 && aix64_flag))
2602 #else
2603 #   define GCC_CHECK_HDR(X) \
2604      ((HEADER (X).f_magic == U802TOCMAGIC && ! aix64_flag) \
2605       || (HEADER (X).f_magic == 0757 && aix64_flag))
2606 #endif
2607
2608 #endif
2609
2610 #ifdef COLLECT_EXPORT_LIST
2611 /* Array of standard AIX libraries which should not
2612    be scanned for ctors/dtors.  */
2613 static const char *const aix_std_libs[] = {
2614   "/unix",
2615   "/lib/libc.a",
2616   "/lib/libm.a",
2617   "/lib/libc_r.a",
2618   "/lib/libm_r.a",
2619   "/usr/lib/libc.a",
2620   "/usr/lib/libm.a",
2621   "/usr/lib/libc_r.a",
2622   "/usr/lib/libm_r.a",
2623   "/usr/lib/threads/libc.a",
2624   "/usr/ccs/lib/libc.a",
2625   "/usr/ccs/lib/libm.a",
2626   "/usr/ccs/lib/libc_r.a",
2627   "/usr/ccs/lib/libm_r.a",
2628   NULL
2629 };
2630
2631 /* This function checks the filename and returns 1
2632    if this name matches the location of a standard AIX library.  */
2633 static int ignore_library (const char *);
2634 static int
2635 ignore_library (const char *name)
2636 {
2637   const char *const *p = &aix_std_libs[0];
2638   while (*p++ != NULL)
2639     if (! strcmp (name, *p)) return 1;
2640   return 0;
2641 }
2642 #endif /* COLLECT_EXPORT_LIST */
2643
2644 #if defined (HAVE_DECL_LDGETNAME) && !HAVE_DECL_LDGETNAME
2645 extern char *ldgetname (LDFILE *, GCC_SYMENT *);
2646 #endif
2647
2648 /* COFF version to scan the name list of the loaded program for
2649    the symbols g++ uses for static constructors and destructors.
2650
2651    The constructor table begins at __CTOR_LIST__ and contains a count
2652    of the number of pointers (or -1 if the constructors are built in a
2653    separate section by the linker), followed by the pointers to the
2654    constructor functions, terminated with a null pointer.  The
2655    destructor table has the same format, and begins at __DTOR_LIST__.  */
2656
2657 static void
2658 scan_prog_file (const char *prog_name, enum pass which_pass)
2659 {
2660   LDFILE *ldptr = NULL;
2661   int sym_index, sym_count;
2662   int is_shared = 0;
2663
2664   if (which_pass != PASS_FIRST && which_pass != PASS_OBJ)
2665     return;
2666
2667 #ifdef COLLECT_EXPORT_LIST
2668   /* We do not need scanning for some standard C libraries.  */
2669   if (which_pass == PASS_FIRST && ignore_library (prog_name))
2670     return;
2671
2672   /* On AIX we have a loop, because there is not much difference
2673      between an object and an archive. This trick allows us to
2674      eliminate scan_libraries() function.  */
2675   do
2676     {
2677 #endif
2678       /* Some platforms (e.g. OSF4) declare ldopen as taking a
2679          non-const char * filename parameter, even though it will not
2680          modify that string.  So we must cast away const-ness here,
2681          which will cause -Wcast-qual to burp.  */
2682       if ((ldptr = ldopen ((char *)prog_name, ldptr)) != NULL)
2683         {
2684           if (! MY_ISCOFF (HEADER (ldptr).f_magic))
2685             fatal ("%s: not a COFF file", prog_name);
2686
2687           if (GCC_CHECK_HDR (ldptr))
2688             {
2689               sym_count = GCC_SYMBOLS (ldptr);
2690               sym_index = GCC_SYMZERO (ldptr);
2691
2692 #ifdef COLLECT_EXPORT_LIST
2693               /* Is current archive member a shared object?  */
2694               is_shared = HEADER (ldptr).f_flags & F_SHROBJ;
2695 #endif
2696
2697               while (sym_index < sym_count)
2698                 {
2699                   GCC_SYMENT symbol;
2700
2701                   if (ldtbread (ldptr, sym_index, &symbol) <= 0)
2702                     break;
2703                   sym_index += GCC_SYMINC (symbol);
2704
2705                   if (GCC_OK_SYMBOL (symbol))
2706                     {
2707                       char *name;
2708
2709                       if ((name = ldgetname (ldptr, &symbol)) == NULL)
2710                         continue;               /* Should never happen.  */
2711
2712 #ifdef XCOFF_DEBUGGING_INFO
2713                       /* All AIX function names have a duplicate entry
2714                          beginning with a dot.  */
2715                       if (*name == '.')
2716                         ++name;
2717 #endif
2718
2719                       switch (is_ctor_dtor (name))
2720                         {
2721                         case 1:
2722                           if (! is_shared)
2723                             add_to_list (&constructors, name);
2724 #if defined (COLLECT_EXPORT_LIST) && !defined (LD_INIT_SWITCH)
2725                           if (which_pass == PASS_OBJ)
2726                             add_to_list (&exports, name);
2727 #endif
2728                           break;
2729
2730                         case 2:
2731                           if (! is_shared)
2732                             add_to_list (&destructors, name);
2733 #if defined (COLLECT_EXPORT_LIST) && !defined (LD_INIT_SWITCH)
2734                           if (which_pass == PASS_OBJ)
2735                             add_to_list (&exports, name);
2736 #endif
2737                           break;
2738
2739 #ifdef COLLECT_EXPORT_LIST
2740                         case 3:
2741 #ifndef LD_INIT_SWITCH
2742                           if (is_shared)
2743                             add_to_list (&constructors, name);
2744 #endif
2745                           break;
2746
2747                         case 4:
2748 #ifndef LD_INIT_SWITCH
2749                           if (is_shared)
2750                             add_to_list (&destructors, name);
2751 #endif
2752                           break;
2753 #endif
2754
2755                         case 5:
2756                           if (! is_shared)
2757                             add_to_list (&frame_tables, name);
2758 #if defined (COLLECT_EXPORT_LIST) && !defined (LD_INIT_SWITCH)
2759                           if (which_pass == PASS_OBJ)
2760                             add_to_list (&exports, name);
2761 #endif
2762                           break;
2763
2764                         default:        /* not a constructor or destructor */
2765 #ifdef COLLECT_EXPORT_LIST
2766                           /* Explicitly export all global symbols when
2767                              building a shared object on AIX, but do not
2768                              re-export symbols from another shared object
2769                              and do not export symbols if the user
2770                              provides an explicit export list.  */
2771                           if (shared_obj && !is_shared
2772                               && which_pass == PASS_OBJ && !export_flag)
2773                             add_to_list (&exports, name);
2774 #endif
2775                           continue;
2776                         }
2777
2778                       if (debug)
2779 #if !defined(EXTENDED_COFF)
2780                         fprintf (stderr, "\tsec=%d class=%d type=%s%o %s\n",
2781                                  symbol.n_scnum, symbol.n_sclass,
2782                                  (symbol.n_type ? "0" : ""), symbol.n_type,
2783                                  name);
2784 #else
2785                         fprintf (stderr,
2786                                  "\tiss = %5d, value = %5ld, index = %5d, name = %s\n",
2787                                  symbol.iss, (long) symbol.value, symbol.index, name);
2788 #endif
2789                     }
2790                 }
2791             }
2792 #ifdef COLLECT_EXPORT_LIST
2793           else
2794             {
2795               /* If archive contains both 32-bit and 64-bit objects,
2796                  we want to skip objects in other mode so mismatch normal.  */
2797               if (debug)
2798                 fprintf (stderr, "%s : magic=%o aix64=%d mismatch\n",
2799                          prog_name, HEADER (ldptr).f_magic, aix64_flag);
2800             }
2801 #endif
2802         }
2803       else
2804         {
2805           fatal ("%s: cannot open as COFF file", prog_name);
2806         }
2807 #ifdef COLLECT_EXPORT_LIST
2808       /* On AIX loop continues while there are more members in archive.  */
2809     }
2810   while (ldclose (ldptr) == FAILURE);
2811 #else
2812   /* Otherwise we simply close ldptr.  */
2813   (void) ldclose(ldptr);
2814 #endif
2815 }
2816 #endif /* OBJECT_FORMAT_COFF */
2817
2818 #ifdef COLLECT_EXPORT_LIST
2819 /* Given a library name without "lib" prefix, this function
2820    returns a full library name including a path.  */
2821 static char *
2822 resolve_lib_name (const char *name)
2823 {
2824   char *lib_buf;
2825   int i, j, l = 0;
2826
2827   for (i = 0; libpaths[i]; i++)
2828     if (libpaths[i]->max_len > l)
2829       l = libpaths[i]->max_len;
2830
2831   lib_buf = xmalloc (l + strlen(name) + 10);
2832
2833   for (i = 0; libpaths[i]; i++)
2834     {
2835       struct prefix_list *list = libpaths[i]->plist;
2836       for (; list; list = list->next)
2837         {
2838           /* The following lines are needed because path_prefix list
2839              may contain directories both with trailing '/' and
2840              without it.  */
2841           const char *p = "";
2842           if (list->prefix[strlen(list->prefix)-1] != '/')
2843             p = "/";
2844           for (j = 0; libexts[j]; j++)
2845             {
2846               sprintf (lib_buf, "%s%slib%s.%s",
2847                        list->prefix, p, name, libexts[j]);
2848 if (debug) fprintf (stderr, "searching for: %s\n", lib_buf);
2849               if (file_exists (lib_buf))
2850                 {
2851 if (debug) fprintf (stderr, "found: %s\n", lib_buf);
2852                   return (lib_buf);
2853                 }
2854             }
2855         }
2856     }
2857   if (debug)
2858     fprintf (stderr, "not found\n");
2859   else
2860     fatal ("library lib%s not found", name);
2861   return (NULL);
2862 }
2863 #endif /* COLLECT_EXPORT_LIST */