OSDN Git Service

Fix minor bugs found by riscos build attempt.
[pf3gnuchains/gcc-fork.git] / gcc / tlink.c
1 /* CYGNUS LOCAL: whole file jason */
2 /* Scan linker error messages for missing template instantiations and provide
3    them.
4
5    Copyright (C) 1995 Free Software Foundation, Inc.
6    Contributed by Jason Merrill (jason@cygnus.com).
7
8 This file is part of GNU CC.
9
10 GNU CC is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
13 any later version.
14
15 GNU CC is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with GNU CC; see the file COPYING.  If not, write to
22 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
23
24 #include <stdio.h>
25 #include <ctype.h>
26 #include "config.h"
27 #include "hash.h"
28 #include "demangle.h"
29
30 #define MAX_ITERATIONS 17
31
32 /* Obstack allocation and deallocation routines.  */
33 #define obstack_chunk_alloc xmalloc
34 #define obstack_chunk_free free
35
36 extern char * xmalloc PARAMS((unsigned));
37 extern void free ();
38 extern char * getenv ();
39
40 /* Defined in collect2.c.  */
41 extern int vflag, debug;
42 extern char *ldout;
43 extern char *c_file_name;
44 extern struct obstack temporary_obstack;
45 extern struct obstack permanent_obstack;
46 extern char * temporary_firstobj;
47
48 /* Defined in the automatically-generated underscore.c.  */
49 extern int prepends_underscore;
50
51 static int tlink_verbose;
52 \f
53 /* Hash table code.  */
54
55 typedef struct symbol_hash_entry
56 {
57   struct hash_entry root;
58   struct file_hash_entry *file;
59   int chosen;
60   int tweaking;
61   int tweaked;
62 } symbol;
63
64 typedef struct file_hash_entry
65 {
66   struct hash_entry root;
67   const char *args;
68   const char *dir;
69   const char *main;
70   int tweaking;
71 } file;
72
73 typedef struct demangled_hash_entry
74 {
75   struct hash_entry root;
76   const char *mangled;
77 } demangled;
78
79 static struct hash_table symbol_table;
80
81 static struct hash_entry *
82 symbol_hash_newfunc (entry, table, string)
83      struct hash_entry *entry;
84      struct hash_table *table;
85      const char *string;
86 {
87   struct symbol_hash_entry *ret = (struct symbol_hash_entry *) entry;
88   if (ret == NULL)
89     {
90       ret = ((struct symbol_hash_entry *)
91              hash_allocate (table, sizeof (struct symbol_hash_entry)));
92       if (ret == NULL)
93         return NULL;
94     }
95   ret = ((struct symbol_hash_entry *)
96          hash_newfunc ((struct hash_entry *) ret, table, string));
97   ret->file = NULL;
98   ret->chosen = 0;
99   ret->tweaking = 0;
100   ret->tweaked = 0;
101   return (struct hash_entry *) ret;
102 }
103
104 static struct symbol_hash_entry *
105 symbol_hash_lookup (string, create)
106      const char *string;
107      boolean create;
108 {
109   return ((struct symbol_hash_entry *)
110           hash_lookup (&symbol_table, string, create, true));
111 }
112
113 static struct hash_table file_table;
114
115 static struct hash_entry *
116 file_hash_newfunc (entry, table, string)
117      struct hash_entry *entry;
118      struct hash_table *table;
119      const char *string;
120 {
121    struct file_hash_entry *ret = (struct file_hash_entry *) entry;
122   if (ret == NULL)
123     {
124       ret = ((struct file_hash_entry *)
125              hash_allocate (table, sizeof (struct file_hash_entry)));
126       if (ret == NULL)
127         return NULL;
128     }
129   ret = ((struct file_hash_entry *)
130          hash_newfunc ((struct hash_entry *) ret, table, string));
131   ret->args = NULL;
132   ret->dir = NULL;
133   ret->main = NULL;
134   ret->tweaking = 0;
135   return (struct hash_entry *) ret;
136 }
137
138 static struct file_hash_entry *
139 file_hash_lookup (string)
140      const char *string;
141 {
142   return ((struct file_hash_entry *)
143           hash_lookup (&file_table, string, true, true));
144 }
145
146 static struct hash_table demangled_table;
147
148 static struct hash_entry *
149 demangled_hash_newfunc (entry, table, string)
150      struct hash_entry *entry;
151      struct hash_table *table;
152      const char *string;
153 {
154   struct demangled_hash_entry *ret = (struct demangled_hash_entry *) entry;
155   if (ret == NULL)
156     {
157       ret = ((struct demangled_hash_entry *)
158              hash_allocate (table, sizeof (struct demangled_hash_entry)));
159       if (ret == NULL)
160         return NULL;
161     }
162   ret = ((struct demangled_hash_entry *)
163          hash_newfunc ((struct hash_entry *) ret, table, string));
164   ret->mangled = NULL;
165   return (struct hash_entry *) ret;
166 }
167
168 static struct demangled_hash_entry *
169 demangled_hash_lookup (string, create)
170      const char *string;
171      boolean create;
172 {
173   return ((struct demangled_hash_entry *)
174           hash_lookup (&demangled_table, string, create, true));
175 }
176 \f
177 /* Stack code.  */
178
179 struct symbol_stack_entry
180 {
181   symbol *value;
182   struct symbol_stack_entry *next;
183 };
184 struct obstack symbol_stack_obstack;
185 struct symbol_stack_entry *symbol_stack;
186
187 struct file_stack_entry
188 {
189   file *value;
190   struct file_stack_entry *next;
191 };
192 struct obstack file_stack_obstack;
193 struct file_stack_entry *file_stack;
194
195 static void
196 symbol_push (p)
197      symbol *p;
198 {
199   struct symbol_stack_entry *ep = (struct symbol_stack_entry *) obstack_alloc
200     (&symbol_stack_obstack, sizeof (struct symbol_stack_entry));
201   ep->value = p;
202   ep->next = symbol_stack;
203   symbol_stack = ep;
204 }
205
206 static symbol *
207 symbol_pop ()
208 {
209   struct symbol_stack_entry *ep = symbol_stack;
210   symbol *p;
211   if (ep == NULL)
212     return NULL;
213   p = ep->value;
214   symbol_stack = ep->next;
215   obstack_free (&symbol_stack_obstack, ep);
216   return p;
217 }
218
219 static void
220 file_push (p)
221      file *p;
222 {
223   struct file_stack_entry *ep;
224
225   if (p->tweaking)
226     return;
227
228   ep = (struct file_stack_entry *) obstack_alloc
229     (&file_stack_obstack, sizeof (struct file_stack_entry));
230   ep->value = p;
231   ep->next = file_stack;
232   file_stack = ep;
233   p->tweaking = 1;
234 }
235
236 static file *
237 file_pop ()
238 {
239   struct file_stack_entry *ep = file_stack;
240   file *p;
241   if (ep == NULL)
242     return NULL;
243   p = ep->value;
244   file_stack = ep->next;
245   obstack_free (&file_stack_obstack, ep);
246   p->tweaking = 0;
247   return p;
248 }
249 \f
250 /* Other machinery.  */
251
252 static void
253 tlink_init ()
254 {
255   char *p;
256
257   hash_table_init (&symbol_table, symbol_hash_newfunc);
258   hash_table_init (&file_table, file_hash_newfunc);
259   hash_table_init (&demangled_table, demangled_hash_newfunc);
260   obstack_begin (&symbol_stack_obstack, 0);
261   obstack_begin (&file_stack_obstack, 0);
262
263   p = getenv ("TLINK_VERBOSE");
264   if (p)
265     tlink_verbose = atoi (p);
266   else
267     {
268       tlink_verbose = 1;
269       if (vflag)
270         tlink_verbose = 2;
271       if (debug)
272         tlink_verbose = 3;
273     }
274 }
275
276 static int
277 tlink_execute (prog, argv, redir)
278      char *prog;
279      char **argv;
280      char *redir;
281 {
282   collect_execute (prog, argv, redir);
283   return collect_wait (prog);
284
285
286 static char *
287 frob_extension (s, ext)
288      char *s, *ext;
289 {
290   char *p = (char *) rindex (s, '/');
291   if (! p)
292     p = s;
293   p = (char *) rindex (p, '.');
294   if (! p)
295     p = s + strlen (s);
296
297   obstack_grow (&temporary_obstack, s, p - s);
298   return obstack_copy0 (&temporary_obstack, ext, strlen (ext));
299 }
300
301 static char *
302 obstack_fgets (stream, ob)
303      FILE *stream;
304      struct obstack *ob;
305 {
306   int c;
307   while ((c = getc (stream)) != EOF && c != '\n')
308     obstack_1grow (ob, c);
309   if (obstack_object_size (ob) == 0)
310     return NULL;
311   obstack_1grow (ob, '\0');
312   return obstack_finish (ob);
313 }
314
315 static char *
316 tfgets (stream)
317      FILE *stream;
318 {
319   return obstack_fgets (stream, &temporary_obstack);
320 }
321
322 static char *
323 pfgets (stream)
324      FILE *stream;
325 {
326   return obstack_fgets (stream, &permanent_obstack);
327 }
328 \f
329 /* Real tlink code.  */
330
331 static void
332 freadsym (stream, f, chosen)
333      FILE *stream;
334      file *f;
335      int chosen;
336 {
337   symbol *sym;
338
339   {
340     char *name = tfgets (stream);
341     sym = symbol_hash_lookup (name, true);
342   }
343
344   if (sym->file == NULL)
345     {
346       symbol_push (sym);
347       sym->file = f;
348       sym->chosen = chosen;
349     }
350   else if (chosen)
351     {
352       if (sym->chosen && sym->file != f)
353         {
354           if (sym->chosen == 1)
355             file_push (sym->file);
356           else
357             {
358               file_push (f);
359               f = sym->file;
360               chosen = sym->chosen;
361             }
362         }
363       sym->file = f;
364       sym->chosen = chosen;
365     }
366 }
367
368 static void
369 read_repo_file (f)
370      file *f;
371 {
372   char c;
373   FILE *stream = fopen (f->root.string, "r");
374
375   if (tlink_verbose >= 2)
376     fprintf (stderr, "collect: reading %s\n", f->root.string);
377
378   while (fscanf (stream, "%c ", &c) == 1)
379     {
380       switch (c)
381         {
382         case 'A':
383           f->args = pfgets (stream);
384           break;
385         case 'D':
386           f->dir = pfgets (stream);
387           break;
388         case 'M':
389           f->main = pfgets (stream);
390           break;
391         case 'P':
392           freadsym (stream, f, 2);
393           break;
394         case 'C':
395           freadsym (stream, f, 1);
396           break;
397         case 'O':
398           freadsym (stream, f, 0);
399           break;
400         }
401       obstack_free (&temporary_obstack, temporary_firstobj);
402     }
403   fclose (stream);
404   if (f->args == NULL)
405     f->args = getenv ("COLLECT_GCC_OPTIONS");
406   if (f->dir == NULL)
407     f->dir = ".";
408 }
409
410 static void
411 maybe_tweak (line, f)
412      char *line;
413      file *f;
414 {
415   symbol *sym = symbol_hash_lookup (line + 2, false);
416
417   if ((sym->file == f && sym->tweaking)
418       || (sym->file != f && line[0] == 'C'))
419     {
420       sym->tweaking = 0;
421       sym->tweaked = 1;
422
423       if (line[0] == 'O')
424         line[0] = 'C';
425       else
426         line[0] = 'O';
427     }
428 }
429
430 static int
431 recompile_files ()
432 {
433   file *f;
434
435   while ((f = file_pop ()) != NULL)
436     {
437       char *line, *command;
438       FILE *stream = fopen (f->root.string, "r");
439       char *outname = frob_extension (f->root.string, ".rnw");
440       FILE *output = fopen (outname, "w");
441
442       while ((line = tfgets (stream)) != NULL)
443         {
444           switch (line[0])
445             {
446             case 'C':
447             case 'O':
448               maybe_tweak (line, f);
449             }
450           fprintf (output, "%s\n", line);
451         }
452       fclose (stream);
453       fclose (output);
454       rename (outname, f->root.string);
455
456       obstack_grow (&temporary_obstack, "cd ", 3);
457       obstack_grow (&temporary_obstack, f->dir, strlen (f->dir));
458       obstack_grow (&temporary_obstack, "; ", 2);
459       obstack_grow (&temporary_obstack, c_file_name, strlen (c_file_name));
460       obstack_1grow (&temporary_obstack, ' ');
461       obstack_grow (&temporary_obstack, f->args, strlen (f->args));
462       obstack_1grow (&temporary_obstack, ' ');
463       command = obstack_copy0 (&temporary_obstack, f->main, strlen (f->main));
464
465       if (tlink_verbose)
466         fprintf (stderr, "collect: recompiling %s\n", f->main);
467       if (tlink_verbose >= 3)
468         fprintf (stderr, "%s\n", command);
469
470       if (system (command) != 0)
471         return 0;
472
473       read_repo_file (f);
474
475       obstack_free (&temporary_obstack, temporary_firstobj);
476     }
477   return 1;
478 }
479
480 static int
481 read_repo_files (object_lst)
482      char **object_lst;
483 {
484   char **object = object_lst;
485
486   for (; *object; object++)
487     {
488       char *p = frob_extension (*object, ".rpo");
489       file *f;
490
491       if (! file_exists (p))
492         continue;
493
494       f = file_hash_lookup (p);
495
496       read_repo_file (f);
497     }
498
499   if (file_stack != NULL && ! recompile_files ())
500     return 0;
501
502   return (symbol_stack != NULL);
503 }
504
505 static void
506 demangle_new_symbols ()
507 {
508   symbol *sym;
509
510   while ((sym = symbol_pop ()) != NULL)
511     {
512       demangled *dem;
513       char *p = cplus_demangle (sym->root.string, DMGL_PARAMS | DMGL_ANSI);
514
515       if (! p)
516         continue;
517
518       dem = demangled_hash_lookup (p, true);
519       dem->mangled = sym->root.string;
520     }
521 }
522
523 static int
524 scan_linker_output (fname)
525      char *fname;
526 {
527   FILE *stream = fopen (fname, "r");
528   char *line;
529
530   while ((line = tfgets (stream)) != NULL)
531     {
532       char *p = line, *q;
533       symbol *sym;
534       int end;
535       
536       while (*p && isspace (*p))
537         ++p;
538
539       if (! *p)
540         continue;
541
542       for (q = p; *q && ! isspace (*q); ++q)
543         ;
544
545       /* Try the first word on the line.  */
546       if (*p == '.')
547         ++p;
548       if (*p == '_' && prepends_underscore)
549         ++p;
550
551       end = ! *q;
552       *q = 0;
553       sym = symbol_hash_lookup (p, false);
554
555       if (! sym && ! end)
556         /* Try a mangled name in `quotes'.  */
557         {
558           demangled *dem = 0;
559           p = (char *) index (q+1, '`');
560           q = 0;
561
562 #define MUL "multiple definition of "
563 #define UND "undefined reference to "
564
565           if (p && (p - line > sizeof (MUL)))
566             {
567               char *beg = p - sizeof (MUL) + 1;
568               *p = 0;
569               if (!strcmp (beg, MUL) || !strcmp (beg, UND))
570                 p++, q = (char *) index (p, '\'');
571             }
572           if (q)
573             *q = 0, dem = demangled_hash_lookup (p, false);
574           if (dem)
575             sym = symbol_hash_lookup (dem->mangled, false);
576         }
577
578       if (sym && sym->tweaked)
579         return 0;
580       if (sym && !sym->tweaking)
581         {
582           if (tlink_verbose >= 2)
583             fprintf (stderr, "collect: tweaking %s in %s\n",
584                      sym->root.string, sym->file->root.string);
585           sym->tweaking = 1;
586           file_push (sym->file);
587         }
588         
589       obstack_free (&temporary_obstack, temporary_firstobj);
590     }
591
592   return (file_stack != NULL);
593 }
594
595 void
596 do_tlink (ld_argv, object_lst)
597      char **ld_argv, **object_lst;
598 {
599   int exit = tlink_execute ("ld", ld_argv, ldout);
600
601   tlink_init ();
602
603   if (exit)
604     {
605       int i = 0;
606
607       /* Until collect does a better job of figuring out which are object
608          files, assume that everything on the command line could be.  */
609       if (read_repo_files (ld_argv))
610         while (exit && i++ < MAX_ITERATIONS)
611           {
612             if (tlink_verbose >= 3)
613               dump_file (ldout);
614             demangle_new_symbols ();
615             if (! scan_linker_output (ldout))
616               break;
617             if (! recompile_files ())
618               break;
619             if (tlink_verbose)
620               fprintf (stderr, "collect: relinking\n");
621             exit = tlink_execute ("ld", ld_argv, ldout);
622           }
623     }
624
625   dump_file (ldout);
626   unlink (ldout);
627   if (exit)
628     {
629       error ("ld returned %d exit status", exit);
630       collect_exit (exit);
631     }
632 }